如何在同一个按钮上添加两个ActionListener来执行Timer.start()/Timer.stop()方法



我试图制作一个秒表,在这里找到的一些youtube视频和代码的帮助下,我得以做到这一点。但所有这些代码都有两个JButton对象,一个用于启动计时器,另一个用于停止计时器。有人能帮我用一个按钮同时执行启动和停止功能吗。提前谢谢。

以下是我尝试过的一件没有成功的事情。

import javax.swing.*;
import java.awt.event.*;
public class Test extends JFrame
{
private Timer t;
private int sec, min, hrs;
static private JPanel p;
private JButton start;
private JLabel l1;
public Test()
{
    p = new JPanel();
    l1 = new JLabel("" + hrs + " : " + min + " : " + sec);
    start = new JButton("Start");
    start.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {
            t = new Timer(1000, new ActionListener() {
                public void actionPerformed(ActionEvent ev)
                {
                    sec++;
                    if (sec == 60)
                    {
                        min++;
                        sec = 0;
                    }
                    if (min == 60)
                    {
                        hrs++;
                        min = 0;
                    }
                    l1.setText("" + hrs + " : " + min + " : " + sec);
                    start.setText("Stop");
                }
            });
            t.start();
            if(start.getText().equals("Stop"))
            {
                start.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent eve)
                    {
                        t.stop();
                    }
                });
            }
        }
    });
    p.add(l1);
    p.add(start);
}
public static void main(String[] args)
{
    Test te = new Test();
    te.add(p);
    te.setSize(240, 360);
    te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    te.setVisible(true);
}
}

试试这样的类:

class ToggleButton extends JButton {
    private boolean selected;
    private String otherText;
    public ToggleButton(String text, String otherText) {
        super(text);
        this.otherText = otherText;
        this.setSelected(true);
        this.fixListener();
    }
    public boolean isSelected() {
        return selected;
    }
    public void setSelected(boolean selected) {
        this.selected = selected;
    }
    private void fixListener() {
        addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                if (isSelected()) {
                    setSelected(false);
                    t.start();
                } else {
                    setSelected(true);
                    t.stop();
                }
                String text = getText();
                setText(otherText);
                otherText = text;
            }
        });
    }
}

这样称呼它:JButton start = new ToggleButton("Start","Stop");

这也意味着,如果计时器也可以通过另一个按钮或方法停止和启动,则需要更新该按钮。这就是为什么setSelected()是公开的。

我还添加了一个计时器类来帮助您使用计时器。通过执行new Timer(ping);对其进行初始化(ping是一个整数,以毫秒为单位显示刻度之间的延迟)。分别使用start()pause()启动和暂停。

public class Timer extends Thread {
    private Thread thread;
    private boolean running;
    private boolean paused;
    private int ping;
    public Time(int ping){
        this.ping = ping;
        running = false;
        paused = true;
    }
    private void loop(){
        while(running){
            if(paused){
                tick();//check at the end
            }
            delay(ping);
        }
    }
    private void delay(int mil) {
        try {
            Thread.sleep(mil);
        } catch (InterruptedException e) {
        }
    }
    public void start() {
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }else{
            paused = false;
        }
    }
    public void pause(){
        paused = true;
    }
    public void reset(){
        thread = null;
        running = false;
        paused = true;
    }
    @Override
    public void run() {
        running = true;
        paused = false;
        loop();
    }
}

将此方法添加到测试类中

public void tick(){
    sec++;
    if (sec >= 60){
        min++;
        sec = sec - 60;
    }
    if (min >= 60){
        hrs++;
        min = min - 60;
    }
}

修复了你的测试类,只需将其更改为:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test extends JFrame {
    private Timer timer;
    private int sec, min, hrs;
    private JPanel panel;
    private JButton start;
    private JLabel label1;
    public Test() {
        panel = new JPanel();
        label1 = new JLabel("" + hrs + " : " + min + " : " + sec);
        timer = new Timer(1000);
        start = new ToggleButton("Start", "Stop");
        panel.add(label1, BorderLayout.NORTH);
        panel.add(start, BorderLayout.SOUTH);
        getContentPane().add(panel, BorderLayout.CENTER);
        setVisible(true);
    }
    public static void main(String[] args) {
        Test test = new Test();
        test.setSize(240, 360);
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    public void tick() {
        sec++;
        if (sec >= 60) {
            min++;
            sec = sec - 60;
        }
        if (min >= 60) {
            hrs++;
            min = min - 60;
        }
        label1.setText("" + hrs + " : " + min + " : " + sec);
    }
    private class ToggleButton extends JButton {
        private boolean selected;
        private String otherText;
        public ToggleButton(String text, String otherText) {
            super(text);
            this.otherText = otherText;
            this.setSelected(true);
            this.fixListener();
        }
        public boolean isSelected() {
            return selected;
        }
        public void setSelected(boolean selected) {
            this.selected = selected;
        }
        private void fixListener() {
            addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    if (isSelected()) {
                        setSelected(false);
                        timer.start();
                    } else {
                        setSelected(true);
                        timer.pause();
                    }
                    String text = getText();
                    setText(otherText);
                    otherText = text;
                }
            });
        }
    }
    private class Timer extends Thread {
        private Thread thread;
        private boolean running;
        private boolean paused;
        private int ping;
        public Timer(int ping) {
            this.ping = ping;
            running = false;
            paused = true;
        }
        private void loop() {
            while (running) {
                if (!paused) {
                    tick();
                }
                delay(ping);
            }
        }
        private void delay(int mil) {
            try {
                Thread.sleep(mil);
            } catch (InterruptedException e) {
            }
        }
        public void start() {
            if (thread == null) {
                thread = new Thread(this);
                thread.start();
            } else {
                paused = false;
            }
        }
        public void pause() {
            paused = true;
        }
        @Override
        public void run() {
            running = true;
            paused = false;
            loop();
        }
    }
}

您可以声明一个表示计时器是否打开的字段。在ActionListener中,您可以在调用该变量时检查其状态,并根据该状态停止或启动计时器。

start.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent eve){
        if(timerIsOn)
            t.stop();
        else
            t.start();
        timerIsOn = !timerIsOn; // This will toggle the value of the variable, so if it was false it will now be true and vice versa
     }
});

timerIsOn替换为您声明的字段的名称,并确保使用值false对其进行初始化。

最新更新