问题
I was reading different threads on the subject which suggested the Swing Timer class or SwingUtilities.InvokeLater
...but I am having a lot of trouble wrapping my head around them.
I used atomicInteger to create my countdown timer and it works fine in the console. However, When I try to incorporate it in Swing, it only updates the starting and ending value (e.g. set a 5 sec countdown will display in the frame: "5" -> after 5 seconds -> "0".
Is there any simple way for me to keep and "refresh" my atomicInteger countdown label, or the only way is using the Swing Timer class?
Thank you for your patience!
ps. not homework, just trying to make myself a custom timer to study. (ie. procrastinating)
I hope this class is enough, please let me know if you need the frame/panel code as well.
private class ClickListener implements ActionListener{
public void actionPerformed(ActionEvent e){
int t_study = 5;
atomicDown.set(t_study);
if (e.getSource() == b_study){
while(atomicDown.get() > 0){
t_study = atomicDown.decrementAndGet();
l_studyTime.setText(Integer.toString(t_study));
try {
Thread.sleep(1000);
}
catch (InterruptedException e1) {
System.out.println("ERROR: Thread.sleep()");
e1.printStackTrace();
}
}
}
else if(e.getSource() == b_exit){
System.exit(0);
}
else
System.out.println("ERROR: button troll");
}
}
回答1:
After turning the code snippet into an SSCCE, this is what I get (which seems to work - as best as I understand the original code).
I have not changed the variable names. Please learn common Java naming conventions1 for class, method & attribute names & use it consistently.
- Specifically names like
b_study
should be more along the lines ofstudyButton
or similar. Some will note that 'button' should not be part of the name, but when you have a GUI with both a 'Study' button & label, I don't see any other logical way to separate them.
import java.awt.event.*;
import javax.swing.*;
import java.util.concurrent.atomic.AtomicInteger;
class TimerTicker {
public static final int STUDY_TIME = 15;
AtomicInteger atomicDown = new AtomicInteger(STUDY_TIME);
JButton b_study;
JButton b_exit;
JLabel l_studyTime;
TimerTicker() {
JPanel gui = new JPanel();
b_study = new JButton("Study");
ClickListener listener = new ClickListener();
b_study.addActionListener(listener);
gui.add(b_study);
b_exit = new JButton("Exit");
b_exit.addActionListener(listener);
gui.add(b_exit);
l_studyTime = new JLabel("" + atomicDown.get());
gui.add(l_studyTime);
JOptionPane.showMessageDialog(null, gui);
}
private class ClickListener implements ActionListener {
Timer timer;
public void actionPerformed(ActionEvent e){
if (e.getSource() == b_study) {
ActionListener countDown = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (!(atomicDown.get() > 0)) {
timer.stop();
// reset the count.
atomicDown.set(STUDY_TIME);
} else {
l_studyTime.setText(
Integer.toString(
atomicDown.decrementAndGet()));
}
}
};
timer = new Timer(1000,countDown);
timer.start();
} else if(e.getSource() == b_exit) {
System.exit(0);
} else {
System.out.println("ERROR: button troll");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TimerTicker();
}
});
}
}
来源:https://stackoverflow.com/questions/10021969/java-how-to-continuously-update-jlabel-which-uses-atomicinteger-to-countdown-af