how to update a jLabel every time with a while loop with a delay
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { 开发者_JAVA百科
int count = jSlider1.getValue();
int delay = jSlider2.getValue();
int valueOfSlider = jSlider2.getValue();
int valueOfSlider2 = jSlider1.getValue();
while (count > 0)
{
count--;
String count2 = ""+count;
jLabel3.setText(count2);
try {Thread.sleep(delay); }
catch (InterruptedException ie) { }
}
It will eventually show the final number on the jLabel but it does not incrementally update the number. any help
Swing is single-threaded. Therefore, long-running tasks should never take place in the EDT. This includes sleeping. Instead, use a javax.swing.Timer
. This will delay in a background thread, and then post an action to be executed in the EDT.
See also:
- How to Use Swing Timers
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public final class JLabelUpdateDemo {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame("Update JLabel Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(JTimerLabel.getInstance());
frame.setSize(new Dimension(275, 75)); // used for demonstration purposes
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer t = new Timer(1000, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
int val = Integer.valueOf(JTimerLabel.getInstance().getText());
JTimerLabel.getInstance().setText(String.valueOf(++val));
}
});
t.start();
}
private static final class JTimerLabel extends JLabel{
private static JTimerLabel INSTANCE;
private JTimerLabel(){
super(String.valueOf(0));
setFont(new Font("Courier New", Font.BOLD, 18));
}
public static final JTimerLabel getInstance(){
if(INSTANCE == null){
INSTANCE = new JTimerLabel();
}
return INSTANCE;
}
}
}
This SSCCE imitates a counter that will count up from 0
every second (i.e. update the JLabel
instance) until the application is terminated.
Your problem is that your doing something time consuming in an ActionPerformed callback, which executes in the event thread. In callbacks, you should do something quickly and return, even if that "something" is spawning a thread. The GUI can't update while you're occupying the event thread, it will only update after your callback returns.
精彩评论