4

I'm new to Java and after reading many articles about threads and swing I understood that all the invocations of Swing methods should be done on the EDT because Swing is not thread safe. however, I already wrote a couple of quite long Swing applications before reading about the EDT. and all of my applications ran quite fine. So my question is were my Swing applications running on the EDT by default or were they running on a different thread and i was just lucky not to have any issues with them? Like for example if I add a JButton to a JPanel or JFrame, or if I simply call a JTextField's Field.setText(), will these operations be running on the EDT by default or no? and if the answer is no, then do I have to explicitly send all my Swing component's methods implementations to run on the EDT by invoking SwingUtilities.invokeLater()

Thanks

GamefanA
  • 1,555
  • 2
  • 16
  • 23
  • This question contains some tools that can automatically detect mistakes (note that they don't find all mistakes, because they only monitor repaints). http://stackoverflow.com/questions/3014972/swing-verify-code-on-event-dispatch-thread-at-runtime – Thirler Aug 09 '14 at 12:55

3 Answers3

6

Remember objects don't live on threads, only execution of methods happens on a thread.

All action emerging (through listeners) from swing components automatically run on the EDT.

For instance a button you click, the onClicked() function will already run on the EDT so you don't need to do anything.

If you don't create any threads explicitly, your basic application will have a main thread and an EDT (and many other threads that you don't accidentally get your code executed on, until you start using extra frameworks).

The thing you have to do manually is construct the GUI on the EDT. As you can see here this can be done in your main thread as follows:

   SwingUtilities.invokeLater(new Runnable() { 
        public void run() {            
            MyWindow window = new MyWindow ();
            window.setVisible(true);
        }
    });

If you fail to use the EDT correctly. Everything will seem to work fine, but every now and then you can get very strange behavior (because two threads will be doing things instead of one).

So in summary you have to use invokeLater(), or in some exceptions invokeNow() in the following cases:

  1. Constructing Swing components from the main thread.
  2. Calling swing components from your personally created threads.
  3. Calling swing components from events on threads created by frameworks.

This question contains some tools that can help you automatically detect errors (not all though).

Community
  • 1
  • 1
Thirler
  • 20,239
  • 14
  • 63
  • 92
4

where my Swing applications running on the EDT by default or were they running on a diffrent thread and i was just lucky not to have any issues with them?

They were mostly being ran on the EDT. All the painting and updating that Swing does by itself is on the EDT. Anything you do specifically in your code base that you know wasn't on the EDT, is the code that was not on the EDT. So these would be actions like querying the text of a JLabel, or setting the text of a JLabel, or initializing the JLabel itself.

The various listener methods that are executed by Swing which you have implemented in your code base are however executed on the EDT (as long as Swing called it, not yourself). So in these methods you can query/modify Swing components, but remember to properly transfer in and out any data you give to a Swing component or queried from a Swing component in a thread-safe manner.

Like for example if I create a JButton and add it to a JPanel or JFrame, are these operations running on the EDT by default or no?

The initialization of the objects happens on whatever thread you created them on, and so are the rest of the modifications of the Swing objects (like adding one component to another). I do not know of any Swing components whose public method implementations are wrapped in their own invokeNow() or invokeLater() call, so it's best to assume all portions of the actions happened on whatever thread you called the original methods on.

do I have to explicitly send all my Swing components and methods to run on the EDT by invokingSwingUtilities.invokeLater()

Yes, or invokeNow()

NESPowerGlove
  • 5,496
  • 17
  • 28
  • Thank you so much, you've been very helpful. from now on I will be more careful and try to send all my Swing methods implementaion to run on the EDT – GamefanA Aug 09 '14 at 07:53
  • @user3769877 No problem. Also a good way to double check your code is on the EDT is to print the result of [isEventDispatchThread()](http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingUtilities.html#isEventDispatchThread--). Helpful when you doubt whether a certain event is on the EDT or not. – NESPowerGlove Aug 09 '14 at 09:30
1

Components will be accessed from within the thread context they are called, wch leads to a problem...

All Swing components (or enough not to matter) MIST be accessed within the context of the Event Dispatching Thread once they have been added to a displayable container (attached to a native peer).

This makes Swing components NOT thread safe and you are responsible for ensuring that they are modified/accessed from the EDT correctly, the framework will NOT do it for you

Take a look at Concurrency in Swing for more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366