Swing API design goals are powerful, flexible and easy to use. In particular, we hope to make programmers to easily establish new Swing components, whether it is from headstream or by extending some of our components. For this purpose, we do not ask Swing components to support multi-threaded access. Instead, we send requests to the component and perform requests in a single thread. This article discusses threads and swing components. The purpose is not only to help you use the Swing API in a thread safe manner, but also explains why we choose the thread solution now. This article includes the following: SLR Rule: Swing thread can only be accessed by one thread at the same time. In general, this thread is event-dispatching thread. Exceptions to the rules: Some operations are guaranteed to be threaded. Event distribution: If you need to access the UI from a place handle or draw code, you can use the invokelater () or invokeAndwait () method of the Swingutilities class. Create a thread: If you need to create a thread-such as working for some cost-consuming capacity or affected by I / O capabilities - you can use a thread tool class such as SwingWorker or Timer. Why do we implement Swing: We will use some background information about Swing threads to end this article. Swing rules are: Once the Swing component is now a realized, all code that may affect or depend on the component status should be executed in the event delivery. This rule may sound a bit scary, but for many simple programs, you can not worry about thread problems. Before we write Swing code, let us first define two terms: realized and event distribution threads (event-dispatching thread). It is also possible to form a Paint () method that is already or may be called. A SWING component as a top window will be added when the following method is called: setvisible (true), show () or (possibly surprised) Pack (). When a window is already chemically, all components therebet are already chemically. Another way to develop a component is to put it into an existing container. You will see some examples of the components later. The event dispatching thread is a thread that performs drawing and event processing. For example, the Paint () and an ActionPerformed () method will automatically be executed in the event dispatch. Another way to put the code in the event dispatching process is the invokelater () method of the Swingutilities class. All code that may affect a dedicated Swing component must be executed in an event dispatch. But this rule has some exceptions: Some methods are thread safety: in the Swing API documentation, thread security methods are marked with the following text: This Method is Thread Safe, Although Most Swing Methods Are Not. (This method is thread security) Although most swing methods are not.
) The GUI of an application can often build and display in the main thread: The following typical code is safe, as long as there is no (swing or other) components are already chemical: public class myapplication {public static void main (String [] args ) {JFRAME F = New Jframe ("labels"); // Add each component // here to the main frame ... f.pack (); f.show (); // Don't do any GUI work ... }} The code shown above is all running in the "main" thread. The call to f.PACK () makes the components below JFrames have been chemically. This means that f.show () call is unsafe and should be executed in the event dispatching process. Despite this, as long as the program does not have a way you see the GUI, JFRAME, or the components inside it almost impossible to receive a PAINT () call before f .Show () returns. Because there is no longer any GUI code after f.show (), all GUI work is transferred from the main thread to the event distribution thread, so the code discussed earlier is actually threaded. The GUI of an applet can be constructed and displayed in the init () method: existing browsers do not draw it before an applet's init () and start () methods are called. Thus, constructing the GUI is secure in an init () method of an applet, as long as you do not call the show () or setvisible method for an object in the applet. By the way, if the SWING component is used in the applet, you must implement subclasses for japplets. Also, the components should be added to the JApplet Content Pane, not directly to the Japplet. For any applet, you should not perform the initialization operation at the time of the init () or start () method; and should start a thread to perform the fee. The following JComponent methods are secure and can be called from any thread: repaint (), revALIDATE (), and invalidate (). The repaint () and revALIDATE () methods are queued for the event distribution thread and call the Paint () and validate () methods separately. The invalidate () method only tag a component and all of its direct ancestors only when you need to confirm. The listener list can be modified by any thread: call addListenertypelistener () and removelistenertypelistener () methods are always secure. Adding / deleting an addition / deletion operation for the listener list does not have any impact on the events in progress. Note: The important difference between the RevalIdate () and the old validate () method is that revAlidate () caches the request and combines a validate () call. This is similar to the repaint () cache and combines the draw request. Most initialized GUI work naturally happened in an event distribution thread. Once GUI is visible, most programs are driven by events, such as buttons, or mouse clicks, which always processed in the event dispatching. However, there are always programs that need to perform some non-event-driven GUI work after GUI is visible. For example: programs that need to be initialized before you need to make a long initialization operation: Such programs should usually display the GUI during initialization, then update or change the GUI. The initialization process should not be carried out in an event dispatch; otherwise, the redraw assembly and event distribution will stop. Despite this, after initialization, the GUI's update / change should still be carried out in an event dispatch, and the reason is thread security.
You must update the GUI program in response to non-AWT events: For example, imagine a server program to get a request from programs that might run on other machines. These requests may arrive at any time and will cause the server to call the server in some possible unknown threads. How do this method call to update the GUI? Execute the GUI update code in the event dispatch. The Swingutilities class provides two ways to help you perform code in an event delivery process: InvokeLater (): Requires some code in the event dispatching process. This method will return immediately and will not wait for the code to complete. InvokeAndwait (): Behavior is similar to invokelater (), except for this method to wait for the code to execute. In general, you can replace this method with invokelater (). Here are some examples of using these APIs. Please refer to "Bingo Example" in "The Java Tutorial", especially the following classes: CardWindow, ControlPane, Player, and OveralllStatusPane. Using the InvokeLater () method You can call the InvokeLater () method from any thread to request the event dispatch running a specific code. You must put the code you want to run into a Run () method of a runnable object and set this RunNable object to the parameter of InvokeLater (). The invokelater () method will return immediately, and the event is sent to send the specified code. This is an example using invokeLater () method: Runnable doWorkRunnable = new Runnable () {public void run () {doWork ();}}; SwingUtilities.invokeLater (doWorkRunnable); using the invokeAndWait () method of the invokeAndWait () method and invokeLater () The method is very similar, in addition to the incident dispatched thread to execute the specified code, except for the incomkeandwait () method. In the case of possible, you should try to use Invokelater () to replace InvokeAndWait (). If you really want to use INVOKEANDWAIT (), make sure the thread calling the invokeAndWait () does not hold the lock that may be needed during the call.
This is a use of the invokeAndWait () example: void showHelloThereDialog () throws Exception {Runnable showModalDialog = new Runnable () {public void run () {JOptionPane.showMessageDialog (myMainFrame, "Hello There");}}; SwingUtilities.invokeAndWait ( SHOWMODALDIALOG); ; 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]);} If you can avoid using threads, it is best to do this. Threads may be difficult to use and make the program's Debug more difficult. In general, the thread is unnecessary to work in strict sense, such as updates to component properties. Anyway, sometimes the thread is necessary. The following is some typical situation using threads: performing a fee-time task without having to send events to lock. Examples include the case where a large amount of calculations will result in a large number of cases (such as initialization), and is blocked for the network or disk I / O. An operation is repeatedly performed, usually a predetermined time period between two operation intervals. Wait a message from the customer. You can use two classes to help you implement threads: SwingWorker: Create a background thread to perform a fee. Timer: Create a thread to perform some code multiple times, execute the delay in inter-interval user definitions. Using the SwingWorker class SwingWorker class is implemented in SwingWorker.java, this class is not included in any release in Java, so you must download it separately. The SwingWorker class made all the dirty work required to implement a background thread. Although many programs do not need the background thread, the background thread is still very useful when the operation is performed, it can improve the performance of the program. SwingWorker's get () method. Here's an example of useing swingworker: To use the SwingWorker class, you first want to implement one of its subclasses. In the subclass, you must implement the construct () method also contains your long operation. When you instantiate SwingWorker's subclasses, SwingWorker creates a thread but does not start it. You want to call your SwingWorker object's start () method to start the thread, then the start () method calls your construct () method. When you need the object returned by the construct () method, you can call the Get () method of the SwingWorker class.
This is an example of using the SwingWorker class: ... // In the main method: final swingworker worker = new swingWorker () {public object construct () {return new expensivedialogcomponent ();}}; worker.start () ;. ..// In the action event processing method: joptionpane.showMessageDialog (f, worker.get ()); When the program's main () method calls the start () method, SwingWorker launches a new thread to instantiate ExpensiveDialogComponent. The main () method also constructs a GUI consisting of a window and a button. When the user clicks the button, the program will block, if necessary, block the ExpensiveDialogComponent creation completion. Then the program displays a mode dialog containing the ExpensiveDialogComponent. You can find the entire program at MyApplication.java. Use the Timer class Timer class to execute or perform one action multiple times by an ActionListener. When you create a timer, you can specify the frequency execution execution, and you can specify the listener of the timer's action event. When the timer is started, the action listener's actionPerformed () method is called (multiple) to perform the operation. The ActionPerformed () method defined by the timer action listener will call in the event dispatch. This means you don't have to use the InvokeLater () method. This is an example of using the Timer class to realize an animation cycle: public class animatorapplicationTINETENDS JFRAME IMPLEments ActionListener {... // Decline the instance variable here to Timer Timer; public AnimatorApplicationTimer (...) {... // Create a timing The device to // call this object Action Handler. Timer = New Timer (DELAY, THIS); Timer.setInitialDelay (0); Timer.Setcoalesce (TRUE); ...} public void startanimation () {if (frozen) {// all don't do anything. Apply noble request // stop transform images. } Else {// Start (or restart) animation! Timer.start ();}} public void stopanimation () {// Stop moving thread. Timer.stop ();} public void actionperformed (ActionEvent E) {// Go to the next frame animation. Framenumber ; // shows. Repaint ();} ...} Performs all user interface code in a thread There are some advantages: Components Developers do not have to understand thread programming: All components in the toolkit of ViewPoint and Trestle must Fully support multi-thread access, making it very difficult to expand, especially for developers who are not proficient in thread programming. Recently, some of the toolkits such as SubARCTIC and IFC use and Swing a similar design.