- A Really Simple GUI
- Coding a Single-Threaded Java GUI
- The Problem with Having Just One Thread
- Multithreaded GUI Issues to Look Out For
- Conclusion
The Problem with Having Just One Thread
Watching the output in Figure 2 is kind of restful for a while, but it gets a bit tedious just waiting and watching! Clearly, it would be nicer if we could interact with the program, even if a screen fill operation is occurring. In other words, it's time to make our little GUI grow up and become multithreaded!
In order to make the GUI multithreaded, I've created a new class called ThreadRichGui.java. This class is very similar to our old friend ThreadBareGui.java. For instance, Listing 4 illustrates the updated actionPerformed() method.
Listing 4 The Updated actionPerformed() Method
public void actionPerformed(ActionEvent e) { String guiActionCommand = e.getActionCommand(); if (guiActionCommand.equals(FillScreenButton)) { fillWithObjects fillerThread = new fillWithObjects(); fillerThread.start(); } else { if (guiActionCommand.equals(ExitScreenButton)) { ConfirmDialog confirm = new ConfirmDialog(); if (confirm.activateDialog() != 0) return; } System.exit(0); } }
Notice in Listing 4 the handler for the fill screen operation. I instantiate an object called fillerThread and I then invoke a method called fillerThread.start(). In other words, I create a thread and start it executing. Listing 5 illustrates the code for the fillWithObjects thread entity.
Listing 5 A Subclass of Thread
private class fillWithObjects extends Thread { public void run() { Graphics g = box.getGraphics(); for (int y = 0; y < FILL_HEIGHT; y = y + OBJECT_SIZE) { for (int x = 0; x < FILL_WIDTH; x = x + OBJECT_SIZE) { g.fillRect(x, y, OBJECT_SIZE, OBJECT_SIZE); justWait(PAUSE); } } } public void justWait(int milliseconds) { try { Thread.sleep(milliseconds); } catch(InterruptedException e) { System.out.println("Unexpected interrupt"); System.exit(0); } } }
The first line of Listing 5 illustrates the fact that the class fillWithObjects is just a subclass of Thread—this is illustrated by the statement extends Thread. As with any sub-classing operation, this means that fillWithObjects now has access to any of the methods available to the Thread class.
It's instructive to compare Listing 5 with its single-threaded counterpart Listing 2. Perhaps the first thing of note is the similarity between the code in the two listings. Moving from single-threaded to multi-threaded operation really isn't that difficult.
The code in Listing 5 now allows you to exit the application during a screen fill operation. So, if you click the Exit button during a screen fill, you'll be asked to confirm that you want to exit the program. In the background (or in another thread of execution), the screen fill continues to work. In other words, now that it's become multithreaded, you're back in control with this program!