This simple issue confuses me. You can display a JAVA GUI application by setting the frames' setVisible
property true
. But in almost all the examples I found on internet they use a separate thread to do the same thing.
They do something like this,
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Frame().setvisible(true); //just take the idea of this line
}
});
I found no difference between the two methods. But there must be some special reason, that's why everyone is doing this.
Can someone explain it..thanks!
Pretty much any operation that invokes Swing methods must be run on the Swing Event Dispatch thread. invokeLater() is the way to ensure that this invariant holds. Read more about this here.
Also note that the same is true about most other GUI toolkits, such as forms in .NET, MFC and others.
Swing is not thread-safe and all components needs to be initialized in the EDT. This will prevent issues such as deadlocking.
Because every modification you do on the GUI should be done on the event dispatching thread. This is how AWT and SWING are meant to work.
This because the redraw is executed on a single thread, by using
invokeLater
you let that thread manage it without having potential issued by the lack of thread safety of Swing. Using that syntax you delegate that instructions to be executed on the appopriate thread, which is the one that manages the GUI elements.Java gui framework is designed as a single thread to enforce thread safety: this technique is called thread confinement. Any gui operation e.g. components creation, model creation, event sent, etc must therefore execute in the Event Dispatch Thread (EDT). The way you describe is one way to queue the operation in the EDT.
The main reason for launching your application in this way is that Swing components are not thread-safe so you need to guarantee which thread your GUI will start from: the one called the
Event Dispatching Thread
(EDT). Without doing this, you can't be sure what thread it will start in, but as noted by several kind commentators, the main thread is guaranteed not to be the EDT.You should only create, access, or modify UI components from within the EDT. Doing otherwise will result in unexpected behavior (if you're lucky) and/or dirty repaints.
Some resources I suggest you become familiar with:
You could also have a read of Why does my boilerplate Java desktop app JFrame use EventQueue.invokeLater in the main method?
UPDATE
This is the blog I've been trying to find :P
This basically explains why it's important to sync your
main
with the EDT before getting started, it also describes some of the details about why.It also describes why many developers make this fundamental mistake when starting their applications (basically, we were told we could, but we never were really allowed to...bad us)
The Swing classes are not thread-safe; they get their thread correctness solely from the fact that all actions on them are executed on the same thread (the Event Dispatch Thread, or EDT). So any time you interact with a Swing object, it must be on the EDT -- and
SwingUtilities.invokeLater
is a good way to do that.Without that call, if you just called
setVisible(true)
from any ol' thread, you wouldn't have any thread safety and theFrame
might not even see the actions of that method. Worse yet, theFrame
could see only some of the actions, breaking internal assumptions and invariants and causing odd behavior, crashes or deadlocks.