source:
Http://blog.9cbs.net/chensheng913/archive/2004/08/23/82575.aspx
The unsensive graphical user interface will reduce the availability of the application. When the following phenomenon occurs, we usually say that this user interface is not sensitive:
Do not respond to the incident;
No updated phenomenon;
These phenomena are largely related to the processing method of the event, and we almost inevitably write methods to respond to the mouse click button, keyboard carriage return. In these methods we have to write some code, trigger some actions at runtime. Common action includes lookup, updating a database, etc. In this article, through the analysis of an example, some basic concepts, common errors, and proposing a solution.
Event-dispatching thread We must remember that the code of the event response method is performed in Event-Dispatching Thread unless you enable another thread. So what is EVENT-DISPATCHING THREAD? Single thread rules: Once a SWING component is implemented (REALIZED), all code that may affect or depend on the state of this component should be executed in Event-Dispatching Thread. There are two ways to achieve a component: show (), pack (), or setvisible (TRUE) to the top component; add a component to a container that has been implemented. The root cause of a single thread rule is due to the fact that most of the SWING component library is unsafe to multi-threads. In order to support a single thread model, Swing component libraries provide a thread that is specifically to complete these operations related to Swing components, and this thread is Event-Dispatching Thread. Our event response method is usually called by this thread, unless you write code to call these event response methods. One error that is often made herein is the code that is not directly contacted with the modified component in the event response method. Its most likely effect is that the components are slow. Such as the code of the following response button event:
String str = null; this.textArea.settext ("please wait ..."); try {// do something str = "Hello, World!"; Thread.sleep (1000L);} catch InterruptedException E) {E.PrintStackTrace ();} this.textArea.setText (STR);
The effect after the execution is that the button seems to pay for a while until Done. After the appearance, it will only play. The reason is that the update and event response of the SWING component is done in Event-Dispatching Thread, while event responding, Event-Dispatching Thread is occupied by the event response method, so the component will not be updated. It is possible to update the Swing component until the event response method exits. In order to solve this problem, some people may try to update the component by calling the repaint () method:
Final string [] str = new string [1]; this.jtextarea1.settext ("please wait ..."); this.Repaint (); try {thread.sleep (1000L);} catch (interruptedException e) {e) .printStackTrace ();} STR [0] = "DONE."; jtextarea1.settext (Str [0]); but this method does not play the expected effect, buttons still pay for a while, look at the repaint () method The source code will only know the reason.
Paintevent E = New Paintevent (this, Paintevent.Update, New Rectangle (X, Y, Width, Height); Toolkit.Geteventqueue (). Posteent (e);
The repaint () method actually adds an UPDATE event in the event queue, without direct removal of components, and this event can only be assigned after the current event response method ends. Therefore, only the PAINT method is called directly bypass the distribution mechanism to achieve the purpose.
Final string [] str = new string [1]; this.jtextarea1.setText ("please wait ..."); this.paint (this.getgraphics ()); try {thread.sleep (1000L);} catch InterruptedException E) {E.PrintStackTrace ();} STR [0] = "DONE."; JTEXTAREA1.SETTEXT (STR [0]);
This is an update, but there is still the following problems. Although from feeling, the button has already played, but we can't press this button before DONE. It can be said that the button is still fixed, but it is only a state of bounce. Calling redrawing methods cannot fundamentally solve problems, so we need to seek other methods.
Use multi-threaded effective solution is to use multiple threads. First take a look at a better solution, this program is completed in a program of "Rethinking Swing Threading":
Final string [] str = new string [1]; this.jtextarea1.settext ("please wait ..."); this.Repaint (); new thread () {public void Run () {THREAD.SLEP ( 1000L);} catch (interruptedException e) {E.PrintStackTrace ();} str [0] = "Done."; Javax.swing.swingutilities.invokelater (new runnable () {public void run () {jtextarea1.setText STR [0]);}});}}. start ();
In this program, the operation to spend a lot of time is placed in another thread, so that the event response method can return quickly, Event-Dispatching Thread can update the UI and respond to other events. Note that this program uses the InvokeLater () method. The role of the Invokelater () method is to let Event-Dispatching Thread run the established code. Of course, you can also use the InvokeLater () method, but this will violate a single thread principle and bring a certain degree of relatively multi-thread unsafe. To now, the solution seems to be perfect, but let's take a look at the following code to add the following code, although we usually don't do this. Public void paint (java.awt.graphics g) {super.paint (g); g.drawRect (1, 1, 100, 100);
We will find that the rectangle previously drawn is covered, because we don't have to scribble this rectangle, so add the call to the repaint () method at the end.
Final string [] str = new string [1]; this.jtextarea1.settext ("please wait ..."); this.Repaint (); new thread () {public void Run () {THREAD.SLEP ( 1000L);} catch (interruptedException e) {E.PrintStackTrace ();} str [0] = "Done."; Javax.swing.swingutilities.invokelater (new runnable () {public void run () {jtextarea1.setText STR [0]); repaint ();}});}}. start ();
If you think this code is too lack of readability, you can simplify programming by SwingWorker. You can complete the work of the component update by implementing a construct () method to implement a large amount of time and override the finished () method.
this.jTextArea1.setText ( "Please wait ..."); final SwingWorker worker = new SwingWorker () {public Object construct () {try {Thread.sleep (1000L);} catch (InterruptedException e) {e.printStackTrace ( } Return "done."; Public void finished () {jtextarea1.settext (GetValue (). TOSTRING ()); repaint ();}}; worker.start ();
The above programming methods can be called synchronous mode. In addition, the author puts forward a clearer change through the message mechanism to achieve the same function, but it is necessary to write more "asynchronous" methods. Conclusion In short, we are writing using Swing components to remember the following points: 1, don't take too much EVENT-DISPATCHING THREAD; 2. Use Event-Dispatching Thread to execute with the update components; 3, To update the component. Write a reactive graphical user interface still needs to consider a lot of problems, the above is just the most basic part. Interested readers are welcome to discuss.