0

Hello and welcome everyone, this is my first question so I hope that it is a good one. I was exploring the swing API and I came across a question that popped in my head. I basically asked my self if I could build a program that could use a while() loop and display multiple JTextArea's like you could in the console like this:

while(x<100){
    System.out.println("This is the number: " + x)
    x++;
}

I want this to print in the JFrame enter code here but I can't seem to figure out how. I'm attempting to use JTextArea's but I really don't think that is the right approach to it. I tried labels but that did not work at all. Here is the source code.

import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Container;

public class MainFrame extends JFrame{

    public static int x=0;
    public static int y = 0;
    MainFrame(String title){
        super(title);   
        // Set Layout
        setLayout(new BorderLayout());

        while(x<100){
            y++;
            x++;
            System.out.println(x);
            Container pane= getContentPane();
            JTextArea x = new TextArea("Wateva" + y);
            JButton button= new JButton("Wateva man");
            pane.add(button, BorderLayout.SOUTH);
            pane.add(x);
        }
    }
}

In the console x is shown incrementing by 1 each time, meaning the loop runs correctly. The only explanation that I can make out as a beginner programer is that it creates the JTextArea but then it realizes that x has been updated and so it overrides the old JTextArea with a new one and it does this for every number until it gets to 100. I think I am using the wrong type of JComponent but that is why I'm here. So if anyone can give me tips or a solution on how to fix, this would be much appreciated.

nbanic
  • 1,270
  • 1
  • 8
  • 11

1 Answers1

2

Welcome to blocking the Event Dispatching Thread.

The EDT is responsible, for among other things, processing repainting requests. You should never performing any operations that block the EDT, instead, you should using something like a SwingWorker

Take a look at Concurrency in Swing for more details

Updated with example

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestTextArea03 {

    public static void main(String[] args) {
        new TestTextArea03();
    }

    public TestTextArea03() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private JTextArea textArea;

        private TestPane() {
            setLayout(new BorderLayout());
            textArea = new JTextArea(10, 10);
            add(new JScrollPane(textArea));

            new TextWorker().execute();
        }

        public class TextWorker extends SwingWorker<Void, String> {

            @Override
            protected void process(List<String> chunks) {
                for (String text : chunks) {
                    textArea.append(text + "\n");
                }
            }

            @Override
            protected Void doInBackground() throws Exception {
                Thread.sleep(1000);
                for (int x = 0; x < 10; x++) {
                    publish(String.valueOf(x));
                    Thread.sleep(250);
                }
                return null;
            }

        }

    }

}

Or a Swing Timer

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestTextArea03 {

    public static void main(String[] args) {
        new TestTextArea03();
    }

    public TestTextArea03() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private JTextArea textArea;
        private int x;

        private TestPane() {
            setLayout(new BorderLayout());
            textArea = new JTextArea(10, 10);
            add(new JScrollPane(textArea));

            Timer timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    x++;
                    textArea.append(String.valueOf(x) + "\n");
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }        
    }    
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    Or `javax.swing.Timer`, for [example](http://stackoverflow.com/a/5529043/230513). – trashgod Apr 11 '13 at 20:12
  • @Lonenebula To be honest, who knows, but the concept/requirements would be the same :P – MadProgrammer Apr 11 '13 at 20:21
  • Thank you for the quick answer. I learned about the EDT when i was looking at threads in swing. I learned that you are not supposed to preform too complex actions in it. What part of my code exactly "blocked" the EDT. And what do you exactly mean by "blocked"? – Todor Penchev Apr 11 '13 at 20:24
  • The `while-loop` blocked the EDT. Until the method exited, it stopped the EDT from processing any events. – MadProgrammer Apr 11 '13 at 20:32
  • Thank you very much MadProgrammer I appreciated it a lot. :) – Todor Penchev Apr 11 '13 at 20:37