按下时按钮不会重置时间
Button doesn't reset time when pressed
我想创建一个有 2 个按钮“开始”和“停止”的程序。
当我按下 Go 时,程序会找到按下按钮的时间,当我按下 Stop 时,它会找到按下此按钮的时间,然后显示 time2-time1。问题是,当我按下 Go 按钮时,它会显示新的 time2-time1,两者都已重置,但还会打印一个新的重置 time2 减去第一个 time1,就像它卡在一个循环中一样。
go.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
GregorianCalendar timesi= new GregorianCalendar();
int time1 =timesi.get(Calendar.MINUTE);
stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
GregorianCalendar timesi1= new GregorianCalendar();
int time2 =timesi1.get(Calendar.MINUTE);
System.out.println(time2-time1);
}
});
}
});
当我第一次按下 Go 并且 1 分钟过去了时,当我按下 Stop 时它应该打印 1,但是当我按下 go 并且这次已经过去 3 分钟时它打印 34,3 是重置时间和 4是为了旧时光1。我怎样才能改变它,让它只打印 3,同时重置 time1 和 time2?
在 go 的监听器中添加 stop 的动作监听器 是搬起石头砸自己的脚,因为这意味着 stop 可能会 multiple 不必要地添加了听众。因此,与其这样做,不如在 go 的侦听器之外添加 stop 的侦听器一次且仅一次,并且与添加 go 的侦听器的代码级别相同。此外,使 time1 变量成为 class 的私有字段,以便它在停止的侦听器中可见。类似于:
public class MyGui {
private JButton go = new JButton("Go");
private JButton stop = new JButton("stop");
private int time = 0;
public MyGui() {
go.addActionListener(new ActionListener() {
GregorianCalendar timesi = new GregorianCalendar();
// int time1 = timesi.get(Calendar.MINUTE);
time1 = timesi.get(Calendar.MINUTE); // use the field not a local class
});
// stop's listener added at the same level as the go's listener
stop.addActionListener(new ActionListener() {
GregorianCalendar timesi1 = new GregorianCalendar();
int time2 = timesi1.get(Calendar.MINUTE);
System.out.println(time2-time1);
});
// more code here
}
// main method....
}
备注:
- 以上代码未经编译或测试,发布更多是为了展示概念,不要将复制和粘贴作为直接解决方案。
- 最好使用更新更干净的
java.time.LocalTime
class 而不是 java.util.Time
或 GregorianCalendar。
这是一个更完整的示例,它使用了 LocalTime。
在此示例中,goButton 的 ActionListener 将:
- 将 startTime LocalTime 字段设置为当前时间,
LocalTime.now()
- 检查 Swing Timer 是否 运行,如果是,停止它
- 然后创建一个新的Swing Timer并启动它。此 Timer 将每 50 微秒重复检查从开始到当前时间的持续时间,然后用表示此持续时间的文本更新 JLabel
停止按钮的侦听器将:
- 检查开始按钮是否已被按下,如果 startTime 不再为空。
- 如果是这样,它将检查 Swing Timer 计时器是否不为空,如果当前为 运行,则停止它。
- 如果Swing Timer仍然是运行,则停止定时器并设置一个代表停止时间的字段LocalTime。
- 计算起止时间的时差,打印出来
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class TimerGui extends JPanel {
private static final int TIMER_DELAY = 50;
private LocalTime startTime;
private LocalTime stopTime;
private JLabel timerLabel = new JLabel("00:00", SwingConstants.CENTER);
private Timer timer = null;
private JButton goButton = new JButton("Go");
private JButton stopButton = new JButton("Stop");
private JButton exitButton = new JButton("Exit");
public TimerGui() {
// make the timer label's text larger
timerLabel.setFont(timerLabel.getFont().deriveFont(Font.BOLD, 24f));
timerLabel.setBorder(BorderFactory.createTitledBorder("Elapsed Time"));
// alt-key hotkeys for my buttons
goButton.setMnemonic(KeyEvent.VK_G);
stopButton.setMnemonic(KeyEvent.VK_S);
exitButton.setMnemonic(KeyEvent.VK_X);
// add ActionListeners
goButton.addActionListener(e -> {
// reset startTime
startTime = LocalTime.now();
// if timer running, stop it
if (timer != null && timer.isRunning()) {
timer.stop();
}
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
});
stopButton.addActionListener(e -> {
// if start has already been pressed
if (startTime != null) {
// if timer running, stop it
if (timer != null && timer.isRunning()) {
timer.stop();
stopTime = LocalTime.now();
}
long minuteDifference = startTime.until(stopTime, ChronoUnit.MINUTES);
long secondDifference = startTime.until(stopTime, ChronoUnit.SECONDS);
System.out.println("Time difference in minutes: " + minuteDifference);
System.out.println("Time difference in seconds: " + secondDifference);
}
});
exitButton.addActionListener(e -> {
System.exit(0);
});
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 5));
buttonPanel.add(goButton);
buttonPanel.add(stopButton);
buttonPanel.add(exitButton);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(timerLabel, BorderLayout.PAGE_START);
add(buttonPanel);
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
LocalTime endTime = LocalTime.now();
long secondDifference = startTime.until(endTime, ChronoUnit.SECONDS);
int minutes = (int) (secondDifference / 60);
int seconds = (int) (secondDifference % 60);
String timeText = String.format("%02d:%02d", minutes, seconds);
timerLabel.setText(timeText);
}
}
private static void createAndShowGui() {
TimerGui mainPanel = new TimerGui();
JFrame frame = new JFrame("Timer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
我想创建一个有 2 个按钮“开始”和“停止”的程序。 当我按下 Go 时,程序会找到按下按钮的时间,当我按下 Stop 时,它会找到按下此按钮的时间,然后显示 time2-time1。问题是,当我按下 Go 按钮时,它会显示新的 time2-time1,两者都已重置,但还会打印一个新的重置 time2 减去第一个 time1,就像它卡在一个循环中一样。
go.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
GregorianCalendar timesi= new GregorianCalendar();
int time1 =timesi.get(Calendar.MINUTE);
stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
GregorianCalendar timesi1= new GregorianCalendar();
int time2 =timesi1.get(Calendar.MINUTE);
System.out.println(time2-time1);
}
});
}
});
当我第一次按下 Go 并且 1 分钟过去了时,当我按下 Stop 时它应该打印 1,但是当我按下 go 并且这次已经过去 3 分钟时它打印 34,3 是重置时间和 4是为了旧时光1。我怎样才能改变它,让它只打印 3,同时重置 time1 和 time2?
在 go 的监听器中添加 stop 的动作监听器 是搬起石头砸自己的脚,因为这意味着 stop 可能会 multiple 不必要地添加了听众。因此,与其这样做,不如在 go 的侦听器之外添加 stop 的侦听器一次且仅一次,并且与添加 go 的侦听器的代码级别相同。此外,使 time1 变量成为 class 的私有字段,以便它在停止的侦听器中可见。类似于:
public class MyGui {
private JButton go = new JButton("Go");
private JButton stop = new JButton("stop");
private int time = 0;
public MyGui() {
go.addActionListener(new ActionListener() {
GregorianCalendar timesi = new GregorianCalendar();
// int time1 = timesi.get(Calendar.MINUTE);
time1 = timesi.get(Calendar.MINUTE); // use the field not a local class
});
// stop's listener added at the same level as the go's listener
stop.addActionListener(new ActionListener() {
GregorianCalendar timesi1 = new GregorianCalendar();
int time2 = timesi1.get(Calendar.MINUTE);
System.out.println(time2-time1);
});
// more code here
}
// main method....
}
备注:
- 以上代码未经编译或测试,发布更多是为了展示概念,不要将复制和粘贴作为直接解决方案。
- 最好使用更新更干净的
java.time.LocalTime
class 而不是java.util.Time
或 GregorianCalendar。
这是一个更完整的示例,它使用了 LocalTime。
在此示例中,goButton 的 ActionListener 将:
- 将 startTime LocalTime 字段设置为当前时间,
LocalTime.now()
- 检查 Swing Timer 是否 运行,如果是,停止它
- 然后创建一个新的Swing Timer并启动它。此 Timer 将每 50 微秒重复检查从开始到当前时间的持续时间,然后用表示此持续时间的文本更新 JLabel
停止按钮的侦听器将:
- 检查开始按钮是否已被按下,如果 startTime 不再为空。
- 如果是这样,它将检查 Swing Timer 计时器是否不为空,如果当前为 运行,则停止它。
- 如果Swing Timer仍然是运行,则停止定时器并设置一个代表停止时间的字段LocalTime。
- 计算起止时间的时差,打印出来
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class TimerGui extends JPanel {
private static final int TIMER_DELAY = 50;
private LocalTime startTime;
private LocalTime stopTime;
private JLabel timerLabel = new JLabel("00:00", SwingConstants.CENTER);
private Timer timer = null;
private JButton goButton = new JButton("Go");
private JButton stopButton = new JButton("Stop");
private JButton exitButton = new JButton("Exit");
public TimerGui() {
// make the timer label's text larger
timerLabel.setFont(timerLabel.getFont().deriveFont(Font.BOLD, 24f));
timerLabel.setBorder(BorderFactory.createTitledBorder("Elapsed Time"));
// alt-key hotkeys for my buttons
goButton.setMnemonic(KeyEvent.VK_G);
stopButton.setMnemonic(KeyEvent.VK_S);
exitButton.setMnemonic(KeyEvent.VK_X);
// add ActionListeners
goButton.addActionListener(e -> {
// reset startTime
startTime = LocalTime.now();
// if timer running, stop it
if (timer != null && timer.isRunning()) {
timer.stop();
}
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
});
stopButton.addActionListener(e -> {
// if start has already been pressed
if (startTime != null) {
// if timer running, stop it
if (timer != null && timer.isRunning()) {
timer.stop();
stopTime = LocalTime.now();
}
long minuteDifference = startTime.until(stopTime, ChronoUnit.MINUTES);
long secondDifference = startTime.until(stopTime, ChronoUnit.SECONDS);
System.out.println("Time difference in minutes: " + minuteDifference);
System.out.println("Time difference in seconds: " + secondDifference);
}
});
exitButton.addActionListener(e -> {
System.exit(0);
});
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 5));
buttonPanel.add(goButton);
buttonPanel.add(stopButton);
buttonPanel.add(exitButton);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(timerLabel, BorderLayout.PAGE_START);
add(buttonPanel);
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
LocalTime endTime = LocalTime.now();
long secondDifference = startTime.until(endTime, ChronoUnit.SECONDS);
int minutes = (int) (secondDifference / 60);
int seconds = (int) (secondDifference % 60);
String timeText = String.format("%02d:%02d", minutes, seconds);
timerLabel.setText(timeText);
}
}
private static void createAndShowGui() {
TimerGui mainPanel = new TimerGui();
JFrame frame = new JFrame("Timer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}