Why should the main method dispatch the creation of the GUI to the EDT in a swing application?

Asked

Viewed 1,666 times

28

According to the Java specification, much of the Swing API is not Thread-Safe and shall rotate in the Event Dispatch Thread.

Like, after initializing the GUI events are fired from within of the EDT itself, unless you are using threads in background that need to update the UI, this is not usually a problem.

But as the method main runs on its own thread (initial), it is common to use invokeLater to dispatch the GUI display to the EDT:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            exibirTela();
        }
    });
} 

See that, after displaying the screen, the method main does not execute anything else. In theory, no concurrent EDT code seems to be executed in thread leading.

My question is: There is a reason why we have to dispatch the creation of the screen to the EDT?

In the stack overflow in English I found a reference which points to the documentation saying that the thread should not create the GUI because "almost all the code that creates or interacts with Swing components should run on the EDT". Those days however I saw the code of an application that is running for almost 10 years in production. This code creates and displays the JFrame main directly from main; there was never any problem reported about the operation of that application.

In this sense, what would be the possible competition problems? If we do not use invokeLater what will be rotating in the thread and what will be running on the EDT (e.g.: A JFrame is in the thread but its events go to the EDT)?

  • A few years ago I programmed in Swing and I had the habit of starting the Swing interface directly in the Main Class and even it be an extension of the JFrame, I never had a problem, but my memory alerts me about moments that I had to lock some processes since both were executed in the same thread that started Jframe..

2 answers

15


AWT needs a dedicated thread because it should receive keyboard, mouse and events repaint Continuous and fast loop screen (and the Swing runs on top of the AWT). In this way, AWT could not run on some arbitrary user thread because it must necessarily take sole control of the thread.

In addition, the AWT/Swing is not thread-safe. Swing thread-safe would consist of a huge programming effort for a gain at least questionable.

This way, the conclusion is that AWT/Swing has to run in a single thread for it and that no other thread can access it directly. That’s why we have the EDT (Event-Dispatch Thread).

Although in theory it is possible in some cases to manipulate Swing components outside the EDT without having competition problems, this is a rather difficult, dangerous and fragile task, as it is not clear which are the cases where it is safe to do so, and even if some can be found, they can be invalidated by other things that are manipulating Swing, which in turn can also be invalidated by other things. So we can generally assume that It is never safe to manipulate a Swing component outside the EDT.

On the other hand, by adopting the rule that Swing components should be manipulated only in the EDT, all problems of thread-Safety related to this disappear.

It can be argued that a Swing component could be manipulated outside the EDT before it was actually published to Swing. Even, that’s what Sun used to say (up to J2SE 1.4):

Once a Swing Component has been realized, all code that Might affect or Depend on the state of that Component should be executed in the Event-dispatching thread.

What translating into Portuguese is:

Once a Swing component was accomplished, all code that may affect or depend on the state of this component shall be executed in the Event-dispatching thread.

It is understood as "performing" something like publishing the component for Swing to start manipulating it.

FORGET IT THESE DAYS. The reason is that the code that manipulates a Swing component can end up realizing it, and so it is very difficult to know when a Swing component has been realized or not. A call to something like component.setVisible(true) or jframe.pack() usually involve performing, but other simpler calls, even getters may also end up doing so. From Java 5 the recommendation is that any manipulation of a Swing component must be done inside the EDT.

Finally, when creating and manipulating Swing components within the main thread of the program (the one that executes the method main), the rule of manipulating them within the EDT is violated. The solution to this is to use the SwingUtilities.invokeLater(Runnable) or the equivalent EventQueue.invokeLater(Runnable). Depending on the case you can use invokeAndWait instead of invokeLater if any operation must be performed only after the end of the interaction with Swing. The method EventQueue.isDispatchThread() can be used to let a code know if the thread it’s running on is EDT or not.

See more details here: http://www.javaworld.com/article/2077754/core-java/swing-threading-and-the-event-dispatch-thread.html?page=5

13

What happens is that every Swing event will be sent on the EDT. So doing on the EDT while the exibirTela is running no other Swing event will be dispatched or handled. No click or mouse movement.

Now if you believe in main and the creation takes you can have Swing events being handled while your startup code is changing things. For a small screen this may not be a problem, but if you do something time-consuming part of your screen might not be ready when the user starts sending events.

The idea of putting all Swing action in the EDT is to avoid competition in updating components. In general any operation that takes more than 100ms will be noticeable by the user. Also remember that operations like paint may take a while.

I have had programs that produce null Pointer and other exceptions for the sake of running things outside the EDT. Nothing fatal more indicative than something not right in the code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.