Java: How to continuously update JLabel which uses atomicInteger to countdown after ActionListener

拟墨画扇 提交于 2021-01-28 04:00:47

问题


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.

  1. Specifically names like b_study should be more along the lines of studyButton 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!