[英]How to add two ActionListener on the same button to perform Timer.start() / Timer.stop() method
[英]Two JButtons using the same actionListener to Start/Stop Timer
我是Java的新手,可以提供一些帮助。 我试图将计时器的倒计时从设置的时间设置为0。我的功能正常运行,但是我想添加一些功能,以便在计时器倒计时时停止计时器。
这是我的代码(我正在尝试使用MVC来实现)
这是控制部分:
import java.awt.event.*;
import javax.swing.*;
public class StartButton extends JButton implements ActionListener
{
private TimerModel model;
private Timer timer;
private boolean isStarted;
public StartButton(String buttonText, TimerModel model)
{
super(buttonText);
addActionListener(this);
this.model = model;
isStarted = false;
}
public void actionPerformed(ActionEvent evt)
{
if(!isStarted)
{
timer = new Timer(1000, this);
timer.start();
isStarted = true;
}
model.timerCountdown();
}
public void stopTimer()
{
timer.stop();
}
}
我在线上查看了其他一些类似的问题,并在构造函数中进行了尝试(注意:我没有使用实现ActionListener,而是删除了上面的actionPerformed方法):
if(buttonText.equals("Start"))
{
addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(!isStarted)
{
timer = new Timer(1000, this);
timer.start();
isStarted = true;
}
model.timerCountdown();
}
});
}
if(buttonText.equals("Stop"))
{
addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timer.stop();
}
});
}
现在,此部分处理倒计时正常,但是当我单击“停止”按钮时,它会显示一个异常( 请参阅此处的堆栈跟踪 ),并且它将继续倒计时。
我的知识有限,但是我想这与我试图停止计时器的方式有关。
如果有人可以指出正确的方向,或者至少向我解释为什么会发生,我将不胜感激。
同样,如果您不更改JButton本身的基本行为(例如其绘制方式),而是仅在按下时更改按钮的标题和行为,则不要扩展JButton。 而是给每个按钮自己的Action,这是从AbstractAction继承的类中的对象。 考虑这些家伙类似于类固醇上的ActionListeners。 它们具有与ActionListeners相同的功能,因此具有某些功能,因为它们可以轻松更改按钮的标题(无论是否启用),其助记符,图标,...
例如:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class MyTimerGui {
private static final String TITLE = "Flashing Label";
private static final int TIMER_DELAY = 200;
private static final int GAP = 3;
private static final float LABEL_POINTS = 32F;
private JPanel mainPanel = new JPanel();
private JLabel flashyLabel = new JLabel(TITLE, SwingConstants.CENTER);
private Timer timer = new Timer(TIMER_DELAY, new TimerListener());
public MyTimerGui() {
Font font = flashyLabel.getFont();
font = font.deriveFont(LABEL_POINTS);
flashyLabel.setFont(font);
flashyLabel.setOpaque(true);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
buttonPanel.add(new JButton(new StartAction(this, "Start", KeyEvent.VK_S)));
buttonPanel.add(new JButton(new StopAction(this, "Stop", KeyEvent.VK_T)));
buttonPanel.add(new JButton(new ExitAction(this, "Exit", KeyEvent.VK_X)));
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.setLayout(new BorderLayout());
mainPanel.add(flashyLabel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.PAGE_END);
}
public JComponent getMainComponent() {
return mainPanel;
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
flashyLabel.setForeground(null);
flashyLabel.setBackground(null);
}
public void exit() {
timer.stop();
Window win = SwingUtilities.getWindowAncestor(mainPanel);
win.dispose();
}
private class TimerListener implements ActionListener {
private final Color foreground1 = Color.green;
private final Color background1 = Color.red;
@Override
public void actionPerformed(ActionEvent aEvt) {
Color fg = flashyLabel.getForeground();
if (foreground1.equals(fg)) {
flashyLabel.setForeground(null);
flashyLabel.setBackground(null);
} else {
flashyLabel.setForeground(foreground1);
flashyLabel.setBackground(background1);
}
}
}
private class StartAction extends AbstractAction {
private MyTimerGui myTimerGui;
public StartAction(MyTimerGui myTimerGui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myTimerGui = myTimerGui;
}
@Override
public void actionPerformed(ActionEvent e) {
myTimerGui.start();
}
}
private class StopAction extends AbstractAction {
private MyTimerGui myTimerGui;
public StopAction(MyTimerGui myTimerGui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myTimerGui = myTimerGui;
}
@Override
public void actionPerformed(ActionEvent e) {
myTimerGui.stop();
}
}
private class ExitAction extends AbstractAction {
private MyTimerGui myTimerGui;
public ExitAction(MyTimerGui myTimerGui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myTimerGui = myTimerGui;
}
@Override
public void actionPerformed(ActionEvent e) {
myTimerGui.exit();
}
}
private static void createAndShowGui() {
MyTimerGui myTimerGui = new MyTimerGui();
JFrame frame = new JFrame("MyTimer");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(myTimerGui.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
我同意那些不应该扩展JButton
。 逻辑应该在应用程序的主类中执行,该主类与处理组件的创建和存储的类相同。
但是我离题了。 要回答您的问题,我认为确实有两种方法可以解决此问题。 (A)就像在代码中一样将actionListener
存储在类中,或者(B)在对象本身之外编写一个actionListener
。
您是否试图在主类构造函数中实现此构造函数?
我认为您需要类似以下内容的内容(同样在主类中):
StartButton start = new JButton("Start");
StopButton stop = new JButton("Stop");
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// called when the button is pressed
buttonPressed();
}
});
stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// called when the button is pressed
buttonPressed();
}
});
然后,您可以在同一类中编写此方法:
private void buttonPressed() {
System.out.println("Button pressed!");
}
我只是对此进行了快速测试,因此可以确认该方法有效。
PS:如果您确实打算继续使用StartButton
和关联的类,我还建议让按钮包含boolean state
而不是检查按钮的文本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.