Using Other Swing Features |
[PENDING: introduce. This page needs a bit more glue and perhaps a reorg.] This page gives you some examples of using the thread-related Swing API. For conceptual information, see Threads and Swing. For more examples, see the BINGO example, especially the following classes:CardWindow
,ControlPane
,Player
, andOverallStatusPane
.Using the
invokeLater
MethodYou can call
invokeLater
from any thread to request the event-dispatching thread to run certain code. You must put this code in therun
method of aRunnable
object and specify theRunnable
object as the argument toinvokeLater
. TheinvokeLater
method returns immediately, without waiting for the event-dispatching thread to execute the code. Here's an example of usinginvokeLater
:Runnable doWorkRunnable = new Runnable() { public void run() { doWork(); } }; SwingUtilities.invokeLater(doWorkRunnable);Using the
invokeAndWait
MethodThe
invokeAndWait
method is just likeinvokeLater
, except thatinvokeAndWait
doesn't return until the event-dispatching thread has executed the specified code. Whenever possible, you should useinvokeLater
instead ofinvokeAndWait
. If you useinvokeAndWait
, make sure that the thread that callsinvokeAndWait
does not hold any locks that other threads might need while the call is occurring.Here's an example of using
invokeAndWait
:void showHelloThereDialog() throws Exception { Runnable showModalDialog = new Runnable() { public void run() { JOptionPane.showMessageDialog(myMainFrame, "Hello There"); } }; SwingUtilities.invokeAndWait(showModalDialog); }Similarly, a thread that needs access to GUI state, such as the contents of a pair of text fields, might have the following code:
void printTextField() throws Exception { final String[] myStrings = new String[2]; Runnable getTextFieldText = new Runnable() { public void run() { myStrings[0] = textField0.getText(); myStrings[1] = textField1.getText(); } }; SwingUtilities.invokeAndWait(getTextFieldText); System.out.println(myStrings[0] + " " + myStrings[1]); }How to Create Threads
If you can get away with it, avoid using threads. Threads can be difficult to use, and they make programs harder to debug. In general, they just aren't necessary for strictly GUI work, such as updating component properties.
However, sometimes threads are necessary. Here are some typical situations where threads are used:
- To perform a time-consuming task without locking up the event-dispatching thread. Examples include making extensive calculations, doing something that results in many classes being loaded (initialization, for example), and blocking for network or disk I/O.
- To perform an operation repeatedly, usually with some predetermined period of time between operations.
- To wait for messages from clients.
You can use two classes to help you implement threads:
SwingWorker
: Creates a background thread to execute time-consuming operations.
Timer
: Creates a thread that executes some code one or more times, with a user-specified delay between executions. For detailed information about timers, see How to Use Timers.Using the
SwingWorker
ClassThe
Note: The tutorial's implementation of theSwingWorker
class was updated in the January 1999 release of the tutorial; the class has been enhanced to allow programs to safely interrupt the thread. If you are usingSwingWorker
in any of your programs, make sure you are using this version!
SwingWorker
class is implemented inSwingWorker.java
, which is not in the Swing release.SwingWorker
does all the dirty work of implementing a background thread. Although many programs don't need background threads, background threads are sometimes useful for performing time-consuming operations, which can improve the perceived performance of a program.To use the
SwingWorker
class, you first create a subclass of it. In the subclass, you must implement theconstruct
method so that it contains the code to perform your lengthy operation. When you instantiate yourSwingWorker
subclass, theSwingWorker
creates a thread that calls yourconstruct
method. When you need the object returned by theconstruct
method, you call theSwingWorker
'sget
method. Here's an example of usingSwingWorker
:...//in the main method: final SwingWorker worker = new SwingWorker() { public Object construct() { return new ExpensiveDialogComponent(); } }; ...//in an action event handler: JOptionPane.showMessageDialog (f, worker.get());When the program's
main
method creates theSwingWorker
object, theSwingWorker
immediately starts a new thread that instantiatesExpensiveDialogComponent
. Themain
method also constructs a GUI that consists of a window with a button.When the user clicks the button, the program blocks, if necessary, until the
ExpensiveDialogComponent
has been created. The program then shows a modal dialog containing theExpensiveDialogComponent
. You can find the entire program inPasswordDemo.java
. Also, the example program provided in How to Monitor Progress runs a long task in aSwingWorker
thread.
This section is based on an article in The Swing Connection. For more information about Swing thread issues, see the article: Threads and Swing and Using a SwingWorker Thread.
Using Other Swing Features |