Search code examples
javamultithreadingswingevent-dispatch-thread

Swing concurrency and Event-Dispatch Thread


I wonder what is the most acceptable way to work with java swing correctly. I know that in java swing application there are two threads by default Main Thread and Event-Dispatch. I create and show window in this way.

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new MyWindow().initializeAndShow());
    }

But I want to know how should I work with java swing in run-time. I mean, for example setting text in JText on button click. I need to do like this all time?

  SwingUtilities.invokeLater(()-> button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e)
            {

               SwingUtilities.invokeLater(()-jtext.setText("HelloFromAWTThread");
            }
        });      

Is it correct, I think as far as button is also part of UI so listener should be set in dispatch thread or this isn't correct? And setting JText also should be in AWT thread?


Solution

  • It is much simpler as you think.

    Of course, modifications of UI elements (e.h. setting the label text, adding a listener to a button, etc.) must only be done by the event dispatch thread (EDT).

    But most the time this is no real restriction, as all events (e.g. a mouse click on a button or a key press) are processed by the EDT, so your listeners are executed on the EDT too.

    So if you want to register a listener, just do

    button.addActionListener(new ActionListener() {
        /* called by the EDT when the button has been clicked */
        public void actionPerformed(ActionEvent e) {
            jtext.setText("HelloFromAWTThread");
        }
    });
    

    Or even simpler with Java 8 lambdas:

    button.addActionListener(e -> jtext.setText("HelloFromAWTThread"));
    

    It's only getting more complex if you want to run a long-running task, e.g. a time-consuming computation (computing 1 million digits of PI, doing prime factorization etc.), any I/O-operation (loading a file, performing a network request) or any blocking operation, as this will occupy the EDT for too long and prevent it from processing UI events. Therefore, these tasks should run on separate threads. But as it is not allowed to update the UI from other threads than the EDT, you can 'hand-over' a UI-update-task to the EDT by calling SwingUtilities.invokeLater(updateTask).