zoukankan      html  css  js  c++  java
  • 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();
            }
        }
  • 相关阅读:
    Codechef EDGEST 树套树 树状数组 线段树 LCA 卡常
    BZOJ4319 cerc2008 Suffix reconstruction 字符串 SA
    Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
    Codeforces 316G3 Good Substrings 字符串 SAM
    Codechef CHSIGN Change the Signs(May Challenge 2018) 动态规划
    BZOJ1396 识别子串 字符串 SAM 线段树
    CodeForces 516C Drazil and Park 线段树
    CodeForces 516B Drazil and Tiles 其他
    CodeForces 516A Drazil and Factorial 动态规划
    SPOJ LCS2
  • 原文地址:https://www.cnblogs.com/rekent/p/7920379.html
Copyright © 2011-2022 走看看