Can you use the SwingUtilities method ONLY for the GUI interface calls and let your code run on its own, non EDT, thread?
Can you make a small simple program that compiles and executes to demo the problem?
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
You haven't moved the code out of the EDT. ONLY use the EDT when changing the labels. For the sleep do that in your thread.
Its more efficient to get the images ONE time outside of the loop and then reference them inside the loop when they are needed.
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
Never - that is NEVER - use sleep anywhere near Swing. Your while(true) loop runs on the EDT and never returns, thus blocking everything.
For that kind of timing use a javax.swing.timer
Use it to call your button changing method every x millisecs. In that method just change the icon to the next icon and return immediately.
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
If you read the API for the Timer class you will see:
the action handlers for Timers can safely perform operations on Swing components.
James's suggestion for using a Timer is the way to go.
I have gotten your code to work by modifying it in the way I suggested. The only addition was to add a thread for the loop to run on. You must NOT put any long running code on the EDT!!! Make a thread to handle that. The Timer is a natural for your application.
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
how to get the information inside the while loop
Wrong question. Don't use an infinite loop at all. Use a timer. You don't actually have a long-running task, you just have a task that has to be run regularly.
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
But I need to do different things on each call
There are ways to control logic flow: if else statement or switch statement for example
I put each of the GUI calls into SwingUtilities invoke methods and put the loop itself in its own thread.
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
I need to do different things on each call and Timer triggers the same function (or the same set of functions) every 1 sec. How to achieve that ?
Simple switch with a var to tell which icon we need to set each time
int step = 1;
...
public void actionPerformed(ActionEvent e) { // called by Timer
switch (step ) {
case 1: {
// set 1st icon
step = 2;
break;
}
case 2: {
// set 2nd icon
step = 3;
break;
}
// etc
}
or (better) have the icons pre-loaded into an array of ImageIcons, then
int iconNum = 0;
public void actionPerformed(ActionEvent e) { // called by Timer
button.setIcon(imageIcons[iconNum ])
iconNum ++;
if (iconNum >= imageIcons.length) iconNum = 0
}
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
Sure you can create a new thread and sleep in that and use invokeLater, and that should work. But it's a pretty tortuous way to achieve a result for which the swing timer was created, and which timer does in far less code.
Swing timer is actually the class used internally by swing for things like popping up mouse-over tooltips. It's designed to be very efficient and its, obviously, totally integrated into the whole swing infrastructure.
To stop or start your animated icons, just stop or start the timer.
so
No, there;s nothing wrong with it, but it's definitely the second-best solution.
J
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073