Java - 更新现有的秒表代码以包括倒计时 [英] Java - updating existing stopwatch code to include countdown

查看:124
本文介绍了Java - 更新现有的秒表代码以包括倒计时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@HovercraftFullofEels非常友好地通过为我提供以下代码的基础来帮助我,我对其做了一些修改(标记为行完全添加注释和最后的巨大注释,其中包含要放置的代码在文件的某个地方)。



原始文件是一个简单的秒表,我的修改包括3个JTextFields,它包括分钟,秒和CENTI秒(1厘秒) = 1/100秒)。我想要包含一个提交按钮,它允许程序读取这3个文本字段的输入。我编写了单击提交时要调用的方法的代码(包含在最后的巨型注释中)。单击它后,我希望程序立即从秒表开始的值开始倒计时,而不是从单击按钮开始倒计时。例如,如果秒表在用户点击提交并且输入时间为25分钟时已经运行了20分钟,则将开始5分钟的倒计时。



如果这仍然令人困惑,那么你真正需要知道的是我的方法以一条线结束,该线提供了我希望倒计时开始的地方的毫秒表示,在这一点上,我想要倒计时来替换秒表。我还想删除暂停和停止按钮,但不是开始按钮(你会认为它们很容易删除,但我删除了我认为合适并在编译时收到错误)并替换使用单个提交按钮。

  import java.awt.BorderLayout; 
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.Font; //行完全添加
import javax.swing。*;

@SuppressWarnings(serial)
公共类MyTimer2扩展JPanel实现GuiTimer {
private static final String TIME_FORMAT =%02d:%02d:%02d; //从%03d:%03d更改为
private static final int EXTRA_WIDTH = 50;
private JLabel timerLabel = new JLabel();
private TimerControl timerControl = new TimerControl(this);

JTextField minsField,secsField,centisField; //行完全添加 - 这应该是私有的吗?
JLabel冒号,期间; //行完全添加 - 这应该是私有的吗?

public MyTimer2(){
JPanel topPanel = new JPanel();
topPanel.add(timerLabel);

timerLabel.setFont(new Font(Arial,Font.BOLD,64)); //行完全添加

minsField = new JTextField(,2);
secsField = new JTextField(,2);
centisField = new JTextField(,2);

冒号=新JLabel(:);
period = new JLabel(。);

JPanel centerPanel = new JPanel();
centerPanel.add(minsField); //行完全添加
centerPanel.add(冒号); //行完全添加
centerPanel.add(secsField); //行完全添加
centerPanel.add(句号); //行完全添加
centerPanel.add(centisField); //行完全添加

JPanel bottomPanel = new JPanel(); //行完全添加了
bottomPanel.add(new JButton(timerControl.getStartAction())); //从centerPanel改变
bottomPanel.add(new JButton(timerControl.getStopAction())); //从centerPanel更改

setLayout(new BorderLayout());
add(topPanel,BorderLayout.PAGE_START);
add(centerPanel,BorderLayout.CENTER);
add(bottomPanel,BorderLayout.PAGE_END); //行完全添加

setDeltaTime(0);
}

@Override
public void setDeltaTime(int delta){
int mins =(int)delta / 60000; //行完全添加
int secs =((int)delta%60000)/ 1000; //%60000添加了
int centis =((int)delta%1000)/ 10; ///10添加了
timerLabel.setText(String.format(TIME_FORMAT,mins,secs,centis)); //分钟补充; mSecs更改为centis
}

@Override
public Dimension getPreferredSize(){
Dimension superSz = super.getPreferredSize();
if(isPreferredSizeSet()){
return superSz;
}
int prefW = superSz.width + EXTRA_WIDTH;
int prefH = superSz.height;
返回新维度(prefW,prefH);
}

private static void createAndShowGui(){
MyTimer2 mainPanel = new MyTimer2();

JFrame frame = new JFrame(MyTimer2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //从DISPOSE_ON_CLOSE更改
frame.getContentPane()。add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String [] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
createAndShowGui();
}
});
}
}

interface GuiTimer {
public abstract void setDeltaTime(int delta);
}

@SuppressWarnings(serial)
class TimerControl {
private static final int TIMER_DELAY = 10;
private long startTime = 0;
private long pauseTime = 0;
私人定时器计时器;
私人GuiTimer gui;
private StartAction startAction = new StartAction();
private StopAction stopAction = new StopAction();

public TimerControl(GuiTimer gui){
this.gui = gui;
}

public Action getStopAction(){
return stopAction;
}

public Action getStartAction(){
return startAction;
}

enum State {
START(Start,KeyEvent.VK_S),
PAUSE(Pause,KeyEvent.VK_P);
私有字符串文本;
private int mnemonic;

私有状态(String text,int mnemonic){
this.text = text;
this.mnemonic =助记符;
}

public String getText(){
return text;
}

public int getMnemonic(){
return mnemonic;
}
};

私有类StartAction扩展AbstractAction {
私有状态;

public StartAction(){
setState(State.START);
}

public final void setState(State state){
this.state = state;
putValue(NAME,state.getText());
putValue(MNEMONIC_KEY,state.getMnemonic());
}

@Override
public void actionPerformed(ActionEvent e){
if(state == State.START){
if(timer!= null&& timer.isRunning()){
return; //计时器已经运行
}
setState(State.PAUSE);
if(startTime< = 0){
startTime = System.currentTimeMillis();
timer = new Timer(TIMER_DELAY,new TimerListener());
} else {
startTime + = System.currentTimeMillis() - pauseTime;
}
timer.start();
} else if(state == State.PAUSE){
setState(State.START);
pauseTime = System.currentTimeMillis();
timer.stop();
}
}
}

私有类StopAction扩展AbstractAction {
public StopAction(){
super(Stop);
int mnemonic = KeyEvent.VK_T;
putValue(MNEMONIC_KEY,助记符);
}

@Override
public void actionPerformed(ActionEvent e){
if(timer == null){
return;
}
timer.stop();
startAction.setState(State.START);
startTime = 0;
}
}

私有类TimerListener实现ActionListener {
@Override
public void actionPerformed(ActionEvent e){
long time = System .currentTimeMillis();
long delta = time - startTime;
gui.setDeltaTime((int)delta);
}
}

}

/ *不知道这会去哪里,但这是点击提交
的代码
//点击提交...
public void actionPerformed(ActionEvent e)
{
String minsStr = minsField.getText();
String secsStr = secsField.getText();
String centisStr = centisField.getText();
int minsInput = Integer.parseInt(minsStr);
int secsInput = Integer.parseInt(secsStr);
int centisInput = Integer.parseInt(centisStr);

long millis = minsInput * 60000 + secsInput * 1000 + centisInput * 10;

long millisCountdown = millis-delta; //其中delta已经过去毫秒

if(millisCountdown< 0)
JOptionPane.showMessageDialog(输入的时间无效。);

其他
//然后立即从秒表变为倒计时从millisCountdown开始到00:00:00结束

minsField.setText(); // clear minsField
secsField.setText(); // clear secsField
centisField.setText(); // clear centisField
}
* /

如果有人可以帮助我对此,我将不胜感激。不幸的是我不了解Hovercraft的大部分代码,所以我不知道我已经完成了什么。



谢谢!



编辑:这是@ MadProgrammer代码的更新版本:

  import java。 awt.EventQueue; 
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Font;
import java.time.Duration;
import java.time.LocalTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

公共类StopWatch {

public static void main(String [] args){
new StopWatch();
}

public StopWatch(){
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
ex.printStackTrace();
}

JFrame frame = new JFrame(Testing);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

公共静态类TestPane扩展JPanel {

protected static final String TIME_FORMAT =%02d:%02d。%02d;

private LocalTime startTime;
private LocalTime targetTime;

私人JLabel标签;
private JTextField minsField,secsField,centisField;
私人JButton开始,提交;

私人定时器计时器;

public TestPane(){
JPanel topRow = new JPanel();
JPanel centerRow = new JPanel();
JPanel bottomRow = new JPanel();

label = new JLabel(formatDuration(Duration.ofMillis(0)));
topRow.add(label);

minsField = new JTextField(,2);
secsField = new JTextField(,2);
centisField = new JTextField(,2);
centerRow.add(minsField);
centerRow.add(secsField);
centerRow.add(centisField);

start = new JButton(Start);
start.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if(!timer.isRunning()){
startTime = LocalTime.now();
timer.start();
}
}
});

bottomRow.add(start);

submit = new JButton(Submit);
submit.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if(timer.isRunning()){
timer。 stop();

持续时间runningTime = Duration.between(startTime,LocalTime.now());
//从持续时间
$ b $中减去所需的时间量b String minsStr = minsField.getText();
String secsStr = secsField.getText();
String centisStr = centisField.getText();

if(minsStr.matches( \\d + $)&& secsStr.matches(\\\\ + $)&& centisStr.matches(\\\\ + $))
{
int minsInput = Integer.parseInt(minsStr);
int secsInput = In teger.parseInt(secsStr);
int centisInput = Integer.parseInt(centisStr);

if(minsInput> = 0&& secsInput> = 0&& secsInput< 60& centisInput> = 0& centisInput< 100)
{

long millis = minsInput * 60000 + secsInput * 1000 + centisInput * 10;

runningTime = runningTime.minusMillis(millis);

timer.start();

//否定次数
if(runningTime.toMillis()> 0)
{
//当计时器结束时...
targetTime = LocalTime.now()。plus(runningTime);
}

else
{
JOptionPane.showMessageDialog(null,输入的时间无效。);
}
}

其他
{
timer.start();
JOptionPane.showMessageDialog(null,输入的时间无效。);
}
}

其他
{
timer.start();
JOptionPane.showMessageDialog(null,输入的时间无效。);
}

minsField.setText();
secsField.setText();
centisField.setText();
}
}
});

bottomRow.add(submit);

timer = new Timer(10,new ActionListener(){

@Override
public void actionPerformed(ActionEvent e){
if(targetTime! = null){
持续时间= Duration.between(LocalTime.now(),targetTime);
if(duration.toMillis()< = 0){
duration = Duration.ofMillis (0);
timer.stop();
targetTime = null;
}
label.setText(formatDuration(duration));
} else {
//向上计数...
持续时间= Duration.between(startTime,LocalTime.now());
label.setText(formatDuration(duration));
}
}
});

setLayout(new BorderLayout());

label.setFont(new Font(Arial,Font.BOLD,64));

add(topRow,BorderLayout.PAGE_START);
add(centerRow,BorderLayout.CENTER);
add(bottomRow,BorderLayout.PAGE_END);
}

protected String formatDuration(持续时间){
long mins = duration.toMinutes();
duration = duration.minusMinutes(分钟);
long seconds = duration.toMillis()/ 1000;
duration = duration.minusSeconds(seconds);
long centis = duration.toMillis()/ 10;

返回String.format(TIME_FORMAT,分钟,秒,分);
}
}
}


解决方案

这利用了新的Java 8 Time API来简化流程,允许您计算两个时间点之间的持续时间以及算术



参见< a href =https://docs.oracle.com/javase/tutorial/datetime/iso/datetime.html\"rel =nofollow noreferrer>日期和时间类



  import java.awt.EventQueue; 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

公共类StopWatch {

public static void main(String [] args){
new StopWatch();
}

public StopWatch(){
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
ex.printStackTrace();
}

JFrame frame = new JFrame(Testing);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

公共静态类TestPane扩展JPanel {

protected static final String TIME_FORMAT =%02dh%02dm%02ds;

private LocalTime startTime;
private LocalTime targetTime;

私人JLabel标签;
私人JButton开始;

私人定时器计时器;

public TestPane(){
label = new JLabel(formatDuration(Duration.ofMillis(0)));

start = new JButton(Start);
start.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if(timer.isRunning()){
timer。 stop();

持续时间runningTime = Duration.between(startTime,LocalTime.now());
//从持续时间
runningTime = runningTime中减去所需的时间量.minusSeconds(5);

//否定次数
if(runningTime.toMillis()> 0){
//当计时器结束时......
targetTime = LocalTime.now()。plus(runningTime);
timer.start();
}
} else {
startTime = LocalTime.now() ;
timer.start();
}
}
});

timer = new Timer(500,new ActionListener(){

@Override
public void actionPerformed(ActionEvent e){
if(targetTime! = null){
持续时间= Duration.between(LocalTime.now(),targetTime);
if(duration.toMillis()< = 0){
duration = Duration.ofMillis (0);
timer.stop();
targetTime = null;
}
label.setText(formatDuration(duration));
} else {
//向上计数...
持续时间= Duration.between(startTime,LocalTime.now());
label.setText(formatDuration(duration));
}
}
});

setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;

add(label,gbc);
add(start,gbc);

}

protected String formatDuration(持续时间){
long hours = duration.toHours();
duration = duration.minusHours(小时);
long mins = duration.toMinutes();
duration = duration.minusMinutes(分钟);
long seconds = duration.toMillis()/ 1000;

返回String.format(TIME_FORMAT,小时,分钟,秒);
}

}

}



< blockquote>

我还想删除暂停和停止按钮(你会认为它们很容易删除,但我删除了我认为合适的内容并在编译时收到错误)和用单个提交按钮替换它们。


看一下使用JFC / Swing创建GUI 以获取更多详细信息


不幸的是我不理解Hovercraft的大部分代码


我们为您提供的任何其他解决方案都会有相同的结果。您需要将需求分解为可管理的块,计算定时器如何向前移动,然后确定如何使其向后移动,然后找出如何组合这两个概念,以便从运行中减去目标值时间并向后移动。


@HovercraftFullofEels was kind enough to help me by providing me the basis for the following code, which I made some modifications to (marked by "line completely added" comments and the giant comment at the end, which contains code to be placed somewhere in the file).

The original file was a simple stopwatch, and my modifications are to include 3 JTextFields.that take in mins, secs, and CENTIseconds (1 centisecond = 1/100 of a second). I want to include a "Submit" button too, which allows the program to read the input of these 3 text fields. I wrote the code for the method to be invoked when "Submit" is clicked (included in the giant comment at the end). Upon clicking it, I want the program to immediately begin a countdown from those values starting from the time the stopwatch started rather than from the time of clicking the button. For example, if the stopwatch has been running for 20 minutes upon the user clicking "Submit" with an inputted time of 25 minutes, a 5-minute countdown would begin.

If this is still confusing, then all you really need to know is that my method ends with a line that provides a millisecond representation of where I want the countdown to begin, at which point I want the countdown to REPLACE the stopwatch. I also want to remove the "Pause" and "Stop" buttons, but not the "Start" button (you would think they would be easy to remove, but I removed what I thought was appropriate and received an error when compiling) and replace them with the single "Submit" button.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.Font;                     //line completely added
import javax.swing.*;

@SuppressWarnings("serial")
public class MyTimer2 extends JPanel implements GuiTimer {
    private static final String TIME_FORMAT = "%02d:%02d:%02d";   //changed from "%03d:%03d"
    private static final int EXTRA_WIDTH = 50;
    private JLabel timerLabel = new JLabel();
    private TimerControl timerControl = new TimerControl(this);

    JTextField minsField, secsField, centisField;     //line completely added - should this be private?
    JLabel colon, period;                             //line completely added - should this be private?

    public MyTimer2() {
        JPanel topPanel = new JPanel();
        topPanel.add(timerLabel);

        timerLabel.setFont(new Font("Arial", Font.BOLD, 64));     //line completely added

        minsField = new JTextField("", 2);
        secsField = new JTextField("", 2);
        centisField = new JTextField("", 2);

        colon = new JLabel(":");
        period = new JLabel(".");

        JPanel centerPanel = new JPanel();
        centerPanel.add(minsField);          //line completely added
        centerPanel.add(colon);              //line completely added
        centerPanel.add(secsField);          //line completely added
        centerPanel.add(period);             //line completely added
        centerPanel.add(centisField);        //line completely added

        JPanel bottomPanel = new JPanel();                              //line completely added
        bottomPanel.add(new JButton(timerControl.getStartAction()));    //changed from centerPanel
        bottomPanel.add(new JButton(timerControl.getStopAction()));     //changed from centerPanel

        setLayout(new BorderLayout());
        add(topPanel, BorderLayout.PAGE_START);
        add(centerPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.PAGE_END);   //line completely added

        setDeltaTime(0);
    }

    @Override
    public void setDeltaTime(int delta) {
        int mins = (int) delta / 60000;                                          // line completely added
        int secs = ((int) delta % 60000) / 1000;                                 // %60000 added
        int centis = ((int) delta % 1000) / 10;                                  // / 10 added
        timerLabel.setText(String.format(TIME_FORMAT, mins, secs, centis));      // mins added; mSecs changed to centis
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension superSz = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return superSz;
        }
        int prefW = superSz.width + EXTRA_WIDTH;
        int prefH = superSz.height;
        return new Dimension(prefW, prefH);
    }

    private static void createAndShowGui() {
        MyTimer2 mainPanel = new MyTimer2();

        JFrame frame = new JFrame("MyTimer2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  //changed from DISPOSE_ON_CLOSE
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

interface GuiTimer {
    public abstract void setDeltaTime(int delta);
}

@SuppressWarnings("serial")
class TimerControl {
    private static final int TIMER_DELAY = 10;
    private long startTime = 0;
    private long pauseTime = 0;
    private Timer timer;
    private GuiTimer gui;
    private StartAction startAction = new StartAction();
    private StopAction stopAction = new StopAction();

    public TimerControl(GuiTimer gui) {
        this.gui = gui;
    }

    public Action getStopAction() {
        return stopAction;
    }

    public Action getStartAction() {
        return startAction;
    }

    enum State {
        START("Start", KeyEvent.VK_S), 
        PAUSE("Pause", KeyEvent.VK_P);
        private String text;
        private int mnemonic;

        private State(String text, int mnemonic) {
            this.text = text;
            this.mnemonic = mnemonic;
        }

        public String getText() {
            return text;
        }

        public int getMnemonic() {
            return mnemonic;
        }
    };

    private class StartAction extends AbstractAction {
        private State state;

        public StartAction() {
            setState(State.START);
        }

        public final void setState(State state) {
            this.state = state;
            putValue(NAME, state.getText());
            putValue(MNEMONIC_KEY, state.getMnemonic());
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (state == State.START) {
                if (timer != null && timer.isRunning()) {
                    return; // the timer's already running
                }
                setState(State.PAUSE);
                if (startTime <= 0) {
                    startTime = System.currentTimeMillis();
                    timer = new Timer(TIMER_DELAY, new TimerListener());
                } else {
                    startTime += System.currentTimeMillis() - pauseTime;
                }
                timer.start();
            } else if (state == State.PAUSE) {
                setState(State.START);
                pauseTime = System.currentTimeMillis();
                timer.stop();
            }
        }
    }

    private class StopAction extends AbstractAction {
        public StopAction() {
            super("Stop");
            int mnemonic = KeyEvent.VK_T;
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (timer == null) {
                return;
            }
            timer.stop();
            startAction.setState(State.START);
            startTime = 0;
        }
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            long time = System.currentTimeMillis();
            long delta = time - startTime;
            gui.setDeltaTime((int) delta); 
        }
    }

}

/*not sure where this will go, but this is the code for clicking "Submit"   

   //upon clicking "Submit"...
   public void actionPerformed(ActionEvent e)
   {      
      String minsStr = minsField.getText();
      String secsStr = secsField.getText();
      String centisStr = centisField.getText();
      int minsInput = Integer.parseInt(minsStr);
      int secsInput = Integer.parseInt(secsStr);
      int centisInput = Integer.parseInt(centisStr);

      long millis = minsInput * 60000 + secsInput * 1000 + centisInput * 10;

      long millisCountdown = millis - delta;   //where "delta" is elapsed milliseconds

      if(millisCountdown < 0)
          JOptionPane.showMessageDialog("Invalid time entered.");

      else
          //then immediately change from stopwatch to countdown beginning from millisCountdown and ending at 00:00:00

      minsField.setText("");     //clear minsField
      secsField.setText("");     //clear secsField
      centisField.setText("");   //clear centisField
   }
*/

If anyone could help me with this, I would greatly appreciate it. Unfortunately I don't understand the majority of Hovercraft's code, so I have no clue where to go after what I've already done.

Thank you!

EDIT: Here is the updated version of @MadProgrammer's code:

import java.awt.EventQueue;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Font;
import java.time.Duration;
import java.time.LocalTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class StopWatch {

    public static void main(String[] args) {
        new StopWatch();
    }

    public StopWatch() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final String TIME_FORMAT = "%02d:%02d.%02d";

        private LocalTime startTime;
        private LocalTime targetTime;

        private JLabel label;
        private JTextField minsField, secsField, centisField;
        private JButton start, submit;

        private Timer timer;

        public TestPane() {
            JPanel topRow = new JPanel();
            JPanel centerRow = new JPanel();
            JPanel bottomRow = new JPanel();

            label = new JLabel(formatDuration(Duration.ofMillis(0)));
            topRow.add(label);

            minsField = new JTextField("", 2);
            secsField = new JTextField("", 2);
            centisField = new JTextField("", 2);
            centerRow.add(minsField);
            centerRow.add(secsField);
            centerRow.add(centisField);

            start = new JButton("Start");
            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (!timer.isRunning()) {
                        startTime = LocalTime.now();
                        timer.start();
                    }
                }
            });

            bottomRow.add(start);

            submit = new JButton("Submit");
            submit.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                if (timer.isRunning()) {
                        timer.stop();

                        Duration runningTime = Duration.between(startTime, LocalTime.now());
                        // Subtract the required amount of time from the duration

                        String minsStr = minsField.getText();
                        String secsStr = secsField.getText();
                        String centisStr = centisField.getText();

                        if(minsStr.matches("\\d+$") && secsStr.matches("\\d+$") && centisStr.matches("\\d+$"))
                        {                       
                           int minsInput = Integer.parseInt(minsStr);
                           int secsInput = Integer.parseInt(secsStr);
                           int centisInput = Integer.parseInt(centisStr);

                           if(minsInput >= 0 && secsInput >= 0 && secsInput < 60 && centisInput >= 0 && centisInput < 100)
                           {

                              long millis = minsInput * 60000 + secsInput * 1000 + centisInput * 10;

                              runningTime = runningTime.minusMillis(millis);

                              timer.start();

                              // No negative times
                              if (runningTime.toMillis() > 0)
                              {
                                  // When the timer is to end...
                                  targetTime = LocalTime.now().plus(runningTime);
                              }

                              else
                              {
                                 JOptionPane.showMessageDialog(null, "Invalid time entered.");
                              }
                           }

                           else
                           {
                              timer.start();
                              JOptionPane.showMessageDialog(null, "Invalid time entered.");
                           }
                        }

                        else
                        {
                           timer.start();
                           JOptionPane.showMessageDialog(null, "Invalid time entered.");
                        }

                        minsField.setText("");
                        secsField.setText("");
                        centisField.setText("");
                    }
                }
            });

            bottomRow.add(submit);

            timer = new Timer(10, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    if (targetTime != null) {
                        Duration duration = Duration.between(LocalTime.now(), targetTime);
                        if (duration.toMillis() <= 0) {
                            duration = Duration.ofMillis(0);
                            timer.stop();
                            targetTime = null;
                        }
                        label.setText(formatDuration(duration));
                    } else {
                        // Count up...
                        Duration duration = Duration.between(startTime, LocalTime.now());
                        label.setText(formatDuration(duration));
                    }
                }
            });

            setLayout(new BorderLayout());

            label.setFont(new Font("Arial", Font.BOLD, 64));

            add(topRow, BorderLayout.PAGE_START);
            add(centerRow, BorderLayout.CENTER);
            add(bottomRow, BorderLayout.PAGE_END);
        }

        protected String formatDuration(Duration duration) {
            long mins = duration.toMinutes();
            duration = duration.minusMinutes(mins);
            long seconds = duration.toMillis() / 1000;
            duration = duration.minusSeconds(seconds);
            long centis = duration.toMillis() / 10;

            return String.format(TIME_FORMAT, mins, seconds, centis);
        }
    }
}

解决方案

This makes use of the new Java 8 Time API to simplify the process, allowing your to calculate durations between two points in time as well as arithmetic

See Date and Time Classes

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class StopWatch {

    public static void main(String[] args) {
        new StopWatch();
    }

    public StopWatch() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final String TIME_FORMAT = "%02dh %02dm %02ds";

        private LocalTime startTime;
        private LocalTime targetTime;

        private JLabel label;
        private JButton start;

        private Timer timer;

        public TestPane() {
            label = new JLabel(formatDuration(Duration.ofMillis(0)));

            start = new JButton("Start");
            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (timer.isRunning()) {
                        timer.stop();

                        Duration runningTime = Duration.between(startTime, LocalTime.now());
                        // Subtract the required amount of time from the duration
                        runningTime = runningTime.minusSeconds(5);

                        // No negative times
                        if (runningTime.toMillis() > 0) {
                            // When the timer is to end...
                            targetTime = LocalTime.now().plus(runningTime);
                            timer.start();
                        }
                    } else {
                        startTime = LocalTime.now();
                        timer.start();
                    }
                }
            });

            timer = new Timer(500, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    if (targetTime != null) {
                        Duration duration = Duration.between(LocalTime.now(), targetTime);
                        if (duration.toMillis() <= 0) {
                            duration = Duration.ofMillis(0);
                            timer.stop();
                            targetTime = null;
                        }
                        label.setText(formatDuration(duration));
                    } else {
                        // Count up...
                        Duration duration = Duration.between(startTime, LocalTime.now());
                        label.setText(formatDuration(duration));
                    }
                }
            });

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(label, gbc);
            add(start, gbc);

        }

        protected String formatDuration(Duration duration) {
            long hours = duration.toHours();
            duration = duration.minusHours(hours);
            long mins = duration.toMinutes();
            duration = duration.minusMinutes(mins);
            long seconds = duration.toMillis() / 1000;

            return String.format(TIME_FORMAT, hours, mins, seconds);
        }

    }

}

I also want to remove the "Pause" and "Stop" buttons (you would think they would be easy to remove, but I removed what I thought was appropriate and received an error when compiling) and replace them with the single "Submit" button.

Take a look at Creating a GUI With JFC/Swing for more details

Unfortunately I don't understand the majority of Hovercraft's code

And any other solution we provide you will have the same result. You need to break down you requirements into manageable chunks, work out how the timer moves forward, then work out how you can make it move backwards, then work out how you can combine the two concepts so you can subtract a target value from the running time and move it backwards.

这篇关于Java - 更新现有的秒表代码以包括倒计时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆