Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 435
  • Last Modified:

Modify Swing Components

Sun makes the statement:

"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."

Following this recommandation may cause a lot of additional code,
especially when dealing with GUI events, that trigger time consuming
tasks. I use to write event-driven programs that works like a state
machine: the listener only changes states and NOTHING ELSE. A special
thread contains a state event loop does all the task. It also updates
Swing components. Is this safe enough? (I never had a problem.)
0
pluess
Asked:
pluess
  • 9
  • 8
  • 2
  • +1
4 Solutions
 
sciuriwareCommented:
Simple: the 'actionPerformed()' must launch threads for all consuming processes.
Those can modify Swing components, like setEnabled(), setVisible().
Only adding and removing components to JPanel's and other containers must
be followed by a refresh on that container.
That's the way I've done it for years, but stay in control over those threads!

;JOOP!
0
 
sciuriwareCommented:
Example of SWING modification on the fly:

  JPanel p;
...............

  p.add(someButton);   // Button created because of some event (button?)
  p.revalidate();      // That's all needed.

...............................
  p.remove(someButton); // Not needed anymore.
  p.revalidate();      // Ready.


;JOOP!
0
 
ksivananthCommented:
hey you can launch threads to complete tasks but all the threads should be executed through the event dispatching threads since the swing comp are not thread safe. You can do that using invokeLater and invokeAndWait methods in SwingUtility class
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
sciuriwareCommented:
>>> but all the threads should be executed through the event dispatching threads

Nonsense, that's the only way: from the ONE event dispatching thread.
When you click a button, where do you end up? in actionPerformed()
and where is that? Yes, in that thread.

;JOOP!
0
 
ksivananthCommented:
go thruogh the below link,

http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html

hope now it make sense!
0
 
ksivananthCommented:
>>the 'actionPerformed()' must launch threads for all consuming processes.
Those can modify Swing components
>>

   Better you read some article before making such wrong statements!
0
 
sciuriwareCommented:
Funny, what is wrong with that?
You said: "should be executed through the event dispatching threads".
Is there another place than in 'actionPerformed()'?
You may have read more than me, but did you ever apply this?

;JOOP!
0
 
ksivananthCommented:
your code,

public void actionPerformed( ActionEvent ae ){
  Thread thread = new Thread(){
     public void run(){
        //task
     }
  }
} // more possibility for DL

mine,

public void actionPerformed( ActionEvent ae ){
  SwingUtilites.invokeLater( new Runnable(){
     public void run(){
        //task
     }
  } ;
}

Hope u understand the diff now!
0
 
sciuriwareCommented:
Tell me.
0
 
ksivananthCommented:
gothrough the link!
0
 
ksivananthCommented:
and here are some more,

http://java.sun.com/developer/technicalArticles/Threads/swing/

And a clear explanation,

"In Java programs with GUIs that use Swing and/or the AWT, the AWT event handler runs in its own thread. Developers must be careful to not tie up this GUI thread performing time-consuming work, because it is responsible for handling user events and redrawing the GUI. In other words, the program will appear frozen whenever the GUI thread is busy. Swing callbacks, such as Mouse Listeners and Action Listeners are all notified (by having appropriate methods called) by the Swing thread. This approach means that any substantial amount of work the listeners are to do must be performed by having the listener callback method spawn another thread to do the work. The goal is to get the listener callback to return quickly, allowing the Swing thread to respond to other events.

If a Swing thread is running asynchronously, responding to events and repainting the display, how can other threads modify Swing state safely? As I just mentioned, Swing callbacks run in the Swing thread; therefore, they can safely modify Swing data and draw to the screen.

But what about other changes that don't happen as a result of a Swing callback? Having a non-Swing thread modify Swing data is not thread safe. Swing provides two methods to solve this problem: invokeLater() and invokeAndWait(). To modify the Swing state, simply call either of these methods, passing a Runnable object that does the proper work. Because Runnable objects are usually their own threads, you might think that this object is spawned off as a thread to execute. In fact, this is not the case, as that too would not be thread safe. Instead, Swing puts this object in a queue and executes its run method at an arbitrary point in the future. This makes the changes to Swing state thread safe."
0
 
sciuriwareCommented:
You did not understand the thread mechanism.
The magic is in:

  p.revalidate();      // Ready.

I have written professional programs with hundreds of threads that independently painted or modified
the screen.
Of course it could all be my imagination.

pluess, can you react a bit; we are doing this all for YOU!

;JOOP!
0
 
ksivananthCommented:
yes u only understand the thread mechanism, me and all who created the articles are don't!

always prevention is better than cure!
0
 
sciuriwareCommented:
From 1968: Those who can, do; those who can't, teach; those who cannot teach, publish.
Not my words.

;JOOP!
0
 
objectsCommented:
> public void actionPerformed( ActionEvent ae ){
> A special
> thread contains a state event loop does all the task. It also updates
> Swing components. Is this safe enough? (I never had a problem.)

Doesn't sound like it. you should use invokeLater() and invokeAndWait() to update the gui

>  SwingUtilites.invokeLater( new Runnable(){
>     public void run(){
>        //task
>     }
>  } ;
> }

If task is lengthy then that code will block the gui.
0
 
sciuriwareCommented:
objects you are most experienced here.
May I presume that you agree that launching new threads
(or activating other threads) is the right way?

;JOOP!
0
 
objectsCommented:
If the processing is lengthy and you don't want to freeze your gui then you need to start a new thread.
And if that thread needs to update the gui then it should use invokeLater() and invokeAndWait() to do thos updates.
0
 
Mayank SAssociate Director - Product EngineeringCommented:
I would recommend a thread-pool thread to run it if the processing is lengthy (Java 5)
0
 
sciuriwareCommented:
I never needed that. My program was running 100's of threads for weeks (large banking conversion).
I wonder why I never had to use invokeLater() etc.
It worked as a charm.
(JAVA 5 on W2003).

;JOOP!
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> I never needed that.

Thread-pool?
0
 
ksivananthCommented:
>>If the processing is lengthy and you don't want to freeze your gui then you need to start a new thread.
And if that thread needs to update the gui then it should use invokeLater() and invokeAndWait() to do thos updates.
>>

   Exactly, I just posted the code for an example!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 9
  • 8
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now