Java中带有GUI的计时器

问题描述 投票:1回答:2

我试图编写一个小小的Java程序,该程序应该用作计时器。

问题是(可能是)我需要使用Thread.sleep(),并抛出InterruptedException。因此,如果我启动程序,则可以每分钟输入秒钟,但是按“确定”时,什么也不会发生(它也不会在终端中显示任何警告或错误)。

这里是代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.text.NumberFormatter;

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class Timer {

   public static void main(String[] args) throws InterruptedException {

       SwingUtilities.invokeLater(Timer::new);
   }

   private JButton button;
   private JTextField minutes;
   private JTextField seconds;

   Timer() {
       JFrame frame = new JFrame();
       frame.setSize(300, 200);
       frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
       JPanel panel = new JPanel(new BorderLayout());
       JPanel subpanel1 = new JPanel(new GridLayout(1, 2));

       /* 
        * The following lines ensure that the user can 
        * only enter numbers.
       */

       NumberFormat format = NumberFormat.getInstance();
       NumberFormatter formatter = new NumberFormatter(format);
       formatter.setValueClass(Integer.class);
       formatter.setMinimum(0);
       formatter.setMaximum(Integer.MAX_VALUE);
       formatter.setAllowsInvalid(false);
       formatter.setCommitsOnValidEdit(true);

       minutes = new JFormattedTextField(formatter);
       seconds = new JFormattedTextField(formatter);
       minutes.setText("0");
       seconds.setText("0");

       JPanel subpanel2 = new JPanel();

       /*
        * When the user presses the OK-button, the program will
        * start to count down.
       */

       button = new JButton("OK");
       button.addActionListener(new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent actionEvent) {
               try {
                   timer();
               }
               catch(InterruptedException e) {

               }
           }
       });

       JButton button2 = new JButton("Reset");
       button2.addActionListener(new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent actionEvent) {
               minutes.setText("0");
               seconds.setText("0");
               button.setEnabled(true);
           }
       });
       subpanel1.add(minutes);
       subpanel1.add(seconds);
       subpanel2.add(button);
       subpanel2.add(button2);
       panel.add(subpanel1, BorderLayout.CENTER);
       panel.add(subpanel2, BorderLayout.PAGE_END);
       frame.add(panel);
       frame.setVisible(true);
   }


   //Method for the timer
   void timer() throws InterruptedException {
       int min = Integer.valueOf(minutes.getText());
       int sec = Integer.valueOf(seconds.getText());
       button.setEnabled(false);


       while(min > 0 || sec > 0) {
           Thread.sleep(1000);
           if(sec >= 1) {
               sec = sec - 1;
               seconds.setText(String.valueOf(sec));
           }
           else if(sec == 0 || min > 0) {
               sec = 59;
               min = min - 1;
               seconds.setText(String.valueOf(sec));
               minutes.setText(String.valueOf(min));
           }
       }
   }
}

我该怎么做才能使其正常工作?


我知道将Thread.sleep()替换为以下内容:

Timer timer = new Timer(delay, taskPerformer);
timer.setRepeats( false );
timer.start();

现在发生错误:构造函数无法应用于给定的类型(它不需要参数)。我做错了什么? (已定义变量delay和taskPerformer,并且我没有导入java.util.Timer)

java swing
2个回答
2
投票

以下mre显示了如何使用javax.swing.Timer获得所需的倒数:

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.NumberFormatter;

public class MyTimer {

    public static void main(String[] args) throws InterruptedException {
        SwingUtilities.invokeLater(MyTimer::new);
    }

    private final JButton startButton, resetButton;
    private final JTextField minutes;
    private final JTextField seconds;
    private static final int SECOND = 1000;

    private Timer timer;

    MyTimer() {
        JFrame frame = new JFrame();
        //frame.setSize(300, 200);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

        /*
         * The following lines ensure that the user can
         * only enter numbers.
         */
        NumberFormat format = NumberFormat.getInstance();
        NumberFormatter formatter = new NumberFormatter(format);
        formatter.setValueClass(Integer.class);
        formatter.setMinimum(0);
        formatter.setMaximum(Integer.MAX_VALUE);
        formatter.setAllowsInvalid(false);
        formatter.setCommitsOnValidEdit(true);

        minutes = new JFormattedTextField(formatter);
        seconds = new JFormattedTextField(formatter);
        minutes.setText("0");
        seconds.setText("0");

        /*
         * When the user presses the OK-button, the program will
         * start to count down.
         */
        startButton = new JButton("OK");
        startButton.addActionListener(actionEvent -> {
            timer();
        });

        resetButton = new JButton("Reset");
        resetButton.setEnabled(false);
        resetButton.addActionListener(actionEvent -> {
            reset();
        });

        JPanel subpanel1 = new JPanel(new GridLayout(1, 2));
        subpanel1.add(minutes);
        subpanel1.add(seconds);

        JPanel subpanel2 = new JPanel();
        subpanel2.add(startButton);
        subpanel2.add(resetButton);

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(subpanel1, BorderLayout.CENTER);
        panel.add(subpanel2, BorderLayout.PAGE_END);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }

    void timer() {

        startButton.setEnabled(false);

        timer = new Timer(SECOND, e->{

            final int min = Integer.valueOf(minutes.getText());
            final int sec = Integer.valueOf(seconds.getText());
            if(sec == 0 && min == 0){
                reset();
            }else if(sec >= 1) {
                seconds.setText(String.valueOf(sec-1));
            }
            else if(sec == 0 || min > 0) {
                seconds.setText(String.valueOf(59));
                minutes.setText(String.valueOf(min-1));
            }
        });

        timer.setRepeats(true);
        timer.start();
        resetButton.setEnabled(true);
    }

    private void reset() {

        if(timer != null) {
            timer.stop();
        }
        minutes.setText("0");
        seconds.setText("0");
        startButton.setEnabled(true);
    }
}

0
投票

由于您只需要计时器来显示小时,您可以简单地创建一个新线程来处理该时间,而让主线程来处理其他内容,例如用户IO。

© www.soinside.com 2019 - 2024. All rights reserved.