Swing Threads—A Caution!

The GUI components are maintained on the screen by a thread of their own, separate to any threads that you have running in your code. This GUI thread is called the event-dispatching thread, and it takes care of rendering the GUI components and processing any GUI events that take place. An example of a GUI event would be a mouse click, a selection from a menu, or a keystroke on a text field.

The need for thread safety occurs in the system libraries just as much as it does in your code. To work properly, Swing requires that all code that might affect GUI components be executed from the event-dispatching thread! The reason is performance: the GUI library does not have to do synchronization that would be required if multiple threads were potentially adjusting data.

As you know, events are handled by a callback from the window system to an event-handler object you supply. That means that your event-handler code automatically executes in the event-dispatching thread, as it should. But should you try to create new GUI components in another of your threads, your thread will not be synchronized with run-time library data structures. Therefore, the only place where you should create, modify, set visible, set size, or otherwise adjust GUI components is in your event-handler code. Otherwise, you will bring yourself synchronization problems that are difficult to debug.

The following example is erroneous natural-looking code:

public static void main (String[] args) {
    createSomeFrame(); // created in the main thread
    showThatFrame();   // shown by main thread,
    // now that first component is displayed, no more
    // code that affects components may be run from
    // any thread other than the event-dispatching thread
    createSomeOtherGUIComponent(); // WRONG!!!
}

There is one exception to the rule of doing GUI work only in the event-dispatching thread, which fortunately allows us to write our programs in the most natural way. You are allowed to construct a GUI in the application's main method or the JApplet's init method, providing there are no GUI components already on the screen from your program and that you do not further adjust it from this thread after the GUI becomes visible. Most people obey these rules by accident, but you should know about them. For practical purposes, this means if you want to create a new GUI component in response to a GUI event, you must do the instantiation in the code that handles the GUI event.

If you have to do more GUI work from one of your own threads, you can easily put it into the correct thread by using the Runnable interface. One of the Swing utilities takes a Runnable as an argument and runs it in the event dispatching thread. The code is as follows:

Runnable toDoInEvHandlerThread = new Runnable() {
     public void run() {
          // things to do in the event-dispatching thread
          doTheWork();
     }
};

javax.swing.SwingUtilities.invokeLater(toDoInEvHandlerThread);

You should follow this protocol in Swing programs. If you ignore this warning, sooner or later, one of your Swing programs will hit a data race bug, and it will be nearly impossible to reproduce, let alone debug it. When maintaining Swing programs check that invokeLater() has been used where needed.

Now let's look at some Swing components.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.107.254