Java Swing - Use it The Right Way
Ever since I did enough Java GUI work to realise the correct way to use swing components it bugs me every time I see example code floating around that doesn’t follow the rules.“Swing components are not inherently thread safe, and as a general rule, after Swing components have been made visible on the screen, you can only safely modify their data from the event thread.”Ok, so a good rule of note is Sun’s Single Threaded Rule “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.”There are exceptions to the rule but following this rule is good practice.Here are three basic steps you can follow:
- Encapsulate your code in a Runnable object to be passed to the event dispatcher for execution
- Decide whether you need to wait on the result of execution and choose the appropriate invocation format (invokeAndWait() or InvokeLater())
- Use the SwingUtilities class to invoke the event-dispatcher with your invocation format and Runnable object.
Example:import javax.swing.JFrame;public class TestGui extends JFrame {public TestGui() {setSize(320,200);setTitle(”test”);System.out.println(”Gui constructed and running from thread: ” +Thread.currentThread().getName());setVisible(true);try {Thread.sleep(10000);System.out.println(”I’ve finished doing my work”);} catch (InterruptedException e) {e.printStackTrace();}}} import javax.swing.SwingUtilities;public class Test {private TestGui aGui;public static void main(String[] args) {Test test = new Test();test.runGui();System.out.println(”Main programming running on thread: “+Thread.currentThread().getName());System.out.println(”Back doing something else in thread: “+Thread.currentThread().getName());try {for (int i = 0; i Output looks like this:josh@trinity ~/workspace/SwingTest $ java TestMain application running on thread: mainBack doing something else in thread: mainGui constructed and running from thread: AWT-EventQueue-0doing something...doing something...doing something...doing something...doing something...I've finished doing my work Notice how it is now not the main thread that creates and runs the GUI but the AWT-EventQueue-0 thread. In our example the GUI is doing something time consuming (sleeping), but program flow returns to the main thread. Then, the GUI finally finishes its work.The same process of encapsulating your data in a Runnable object and passing it up to the event-dispatcher to execute in it’s own time should occur whenever you modify a swing component after it has been ‘realised’. Again, more often then not you will want to use SwingUtilities.invokeLater() and not tie up the event-dispatcher.Many sources of information can be found on this but two good places to start would be Sun’s Multithreaded Swing Applications tutorial and Threads and Swing. When building larger non-trivial GUI’s I ran into all sorts of freezing, crashing, locking, painting and otherwise nasty behaviour before I learnt to Swing the right way!Tech Tags: java swing java+threading java+gui java+programming

Leave a Reply