• Java 实现一个带提醒的定时器


    定时闹钟预览版EXE下载链接:https://files.cnblogs.com/files/rekent/ReadytoRelax_jar.zip


    功能说明:

      实现了一个休息提醒器,用户首先设定一个倒计时时间(HH:MM:SS),每走完这个时间便会弹出提醒,让用户停止工作,起身休息。

      休息回来工作时只需点击弹窗上的继续工作便可以继续以当前时间继续开始倒计时。


    涉及技术:

      使用类似Timer的定时器来推迟提醒线程的执行便可完成程序的主体部分,再辅以JavaFXAWT来构建GUI界面即可。

      此处使用ScheduledThreadPoolExecutor(点击此处获取该线程池的具体用法)这个线程池来实现延时执行的功能。


    当前涉及的问题:

      点击开始计时后,无法停止计时(无法获取到线程池中的线程并终止它);

      线程池的进程不会因为JavaFX程序的关闭而结束,两者这件没有相互约束的关系;


    源代码(一):(点击事件)

        @FXML private TextField AlarmSecond;
        @FXML private TextField AlarmMiunte;
        @FXML private TextField AlarmHour;
        @FXML private javafx.scene.control.Button begin;
    
        @FXML public void beginCountDown(ActionEvent event) throws AWTException, InterruptedException {
            ScheduledThreadPoolExecutor threadPool=new ScheduledThreadPoolExecutor(10);
            //01.对TextField中数字的判断
            List<Integer> valueList=new ArrayList<>();
            String second=AlarmSecond.getText();
            String miunte=AlarmMiunte.getText();
            String hour=AlarmHour.getText();
            if(second==null){
                second="0";
            }
            if(miunte==null){
                miunte="0";
            }
            if(hour==null){
                hour="0";
            }
            if(!((second.matches("[0-9]*"))&&(miunte.matches("[0-9]*"))&&(hour.matches("[0-9]*")))){
                Alert alert=new Alert(Alert.AlertType.ERROR);
                alert.showAndWait();
                return;
            }
            int int_second=Integer.parseInt(second);
            int int_miunte=Integer.parseInt(miunte);
            int int_hour=Integer.parseInt(hour);
            if(int_hour+int_miunte+int_second<=0){
                Alert alert=new Alert(Alert.AlertType.ERROR);
                alert.showAndWait();
                return;
            }
            valueList.add(int_second);
            valueList.add(int_miunte);
            valueList.add(int_hour);
            //02.计算Long时间类型,单位为MILLISECONDS
            long workingTime=new SpinnerUtil().Time2Millseconds(valueList.get(2),valueList.get(1),valueList.get(0));
            String button_show=begin.getText();
            if(button_show.equals("开始计时")){
                begin.setText("停止计时");
                System.out.println("倒计时时长:"+ valueList.get(2) +"H  "+valueList.get(1)+"M  "+valueList.get(0)+"S");
                //03.创建一个对话框提醒线程
                Runnable CountingAndShow=new Runnable() {
                    @Override
                    public void run() {
                        begin.setText("开始计时");
                        System.out.println("Counting  Over,Have a  rest!");
                        Object[] options = {"继续工作","下班啦"};
                        int response= JOptionPane.showOptionDialog(new JFrame(), "休息一下吧~","",JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
                        if(response==0){
                            try {
                                beginCountDown(event);
                            } catch (AWTException e) {
                                e.printStackTrace();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
    
                    }
                };
                //04.创建一个JavaFX Task任务,并将线程加入线程池中
                Task countingTimer=new Task() {
                    @Override
                    protected Object call() throws Exception {
                        threadPool.schedule(CountingAndShow,workingTime,TimeUnit.MILLISECONDS);
                        return null;
                    }
    
                };
                countingTimer.run();
            }
            else {
                //此处代码并没有效果
                System.out.println("Stop Current Counting");
                threadPool.shutdownNow();
                begin.setText("开始计时");
            }
        }

    源代码(二)以及BUG修复理念

        采用Timer来实现停止功能,在Controller中建立一个私有的Timer对象,这样使每次点击都能是同一个Timer对象。

        停止计时--->调用Timer的Cancel()函数,即可关闭整个Timer(也会结束这个Timer线程),此时再重新实例化一个Timer即可。

        

    private Timer timer;
    
        //新需要保证暂停和开始调用的为同一个Timer对象,所以在前面调用一个私有的对象,在后面在对其实例化
        public Controller() {
            timer=new Timer();
        }
    
        @FXML public void beginCountDown(ActionEvent event) throws AWTException, InterruptedException {
            //01.对TextField中数字的判断
            String second=AlarmSecond.getText();
            String miunte=AlarmMiunte.getText();
            String hour=AlarmHour.getText();
            //02.添加对为空时的自主处理方式
            if(second==null){
                second="0";
            }
            if(miunte==null){
                miunte="0";
            }
            if(hour==null){
                hour="0";
            }
            //03.添加对输入模式的限制
            if(!((second.matches("[0-9]*"))&&(miunte.matches("[0-9]*"))&&(hour.matches("[0-9]*")))){
                Alert alert=new Alert(Alert.AlertType.ERROR);
                alert.showAndWait();
                return;
            }
            int int_second=Integer.parseInt(second);
            int int_miunte=Integer.parseInt(miunte);
            int int_hour=Integer.parseInt(hour);
            if(int_hour<0||int_miunte<0||int_second<0||(int_hour+int_miunte+int_second<=0)){
                Alert alert=new Alert(Alert.AlertType.ERROR);
                alert.showAndWait();
                return;
            }
            //02.计算Long时间类型,单位为MILLISECONDS
            long workingTime=new SpinnerUtil().Time2Millseconds(int_hour,int_miunte,int_second);
            String button_show=begin.getText();
            if(button_show.equals("开始计时")){
                begin.setText("停止计时");
                System.out.println("倒计时时长:"+ int_hour +"H  "+int_miunte+"M  "+int_second+"S");
                //03.创建一个对话框提醒线程
                TimerTask timerTask=new TimerTask() {
                    @Override
                    public void run() {
                        System.out.println("run timeTask");
                        Platform.runLater(() -> {
                            begin.setText("开始计时");
                            System.out.println("Counting  Over,Have a  rest!");
                            Object[] options = {"继续工作", "下班啦"};
                            int response = JOptionPane.showOptionDialog(new JFrame(), "休息一下吧~", "", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
                            if (response == 0) {
                                try {
                                    beginCountDown(event);
                                } catch (AWTException e) {
                                    e.printStackTrace();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                };
                //04.创建一个JavaFX Task任务,并将线程加入线程池中
                Task countingTimer=new Task() {
                    @Override
                    protected Object call() throws Exception {
                        timer.schedule(timerTask,workingTime);
                        return null;
                    }
    
                };
                countingTimer.run();
                System.out.println("run timer");
            }
            else {
                System.out.println("Stop Current Counting");
                timer.cancel();
                begin.setText("开始计时");
                timer=new Timer();
            }
        }
  • 相关阅读:
    The Dole Queue
    [ACM] 九度OJ 1553 时钟
    秘密:之所以不搞军事同盟,俄罗斯
    炮塔郝梦主solo
    男性在下一100层【第三层】——高仿手机银行client接口
    C# 它 抽象类和接口
    PO经批准的订单API
    XDU 1284 寻找礼物
    android JSON数据格式 解析
    select的种种取值
  • 原文地址:https://www.cnblogs.com/rekent/p/7920379.html
Copyright © 2020-2023  润新知