专栏首页日常分享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();
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Torrent文件的解析与转换

    BitTorrent协议的种子文件(英语:Torrent file)可以保存一组文件的元数据。这种格式的文件被BitTorrent协议所定义。扩展名一般为“.t...

    Rekent
  • 网络通信中基于套接字输入流和输出流的创建

      (2)由套接字对象Socket调用getInputStream()或getOutputStream()方法,分别返回具有套接字通信的基础输入流InputSt...

    Rekent
  • Java TCP通信概念及实例

                  <1>TCP:类似于电话系统,建立双向的通信通道,确定连接,话音顺序接听。

    Rekent
  • java Http消息传递之POST和GET两种方法--通过实用工具类来获取服务器资源

    /** * 实用工具类来获取服务器资源 * * get方法传送数据 * * 1、通过path设定传送方式 * 2、创建客户端 *...

    用户3030674
  • 编写你的第一个 StatefulWidget

    前面一篇文章描写了一个打印hello的StatelessWidget的封装,接下来我们应该了解该如何封装一个简单的StatefulWidget,来驱动一次交互,...

    icepy
  • 虚拟现实前传-Three.js实现管壳式换热器3D模型在线查看

    使用threejs实现3D模型加载和显示。3D编程就像拍大片,几个关键东西如下所列:

    周星星9527
  • Glide v3.7源码分析(2)-----RequestManager.load

    可以看到,Glide初始化的时候做了很多的事,初始化了缓存相关的类,任务执行以及缓存管理的引擎,注册了DataLoadProviderRegistry Gene...

    曾大稳
  • org.apache.http.client.methods.HttpPost 两种消息体形式 —— UrlEncodedFormEntity 和 StringEntity

    使用 UrlEncodedFormEntity 来设置 body,消息体内容类似于“KEY1=VALUE1&KEY2=VALUE2&...”这种形式,服务端接收...

    LeoXu
  • 利用Boost影响Lucene查询结果的排序

    以下代码在Lucene2.1下通过,主要是通过设置Document的Boost来影响文档的权重,以达到控制查询结果顺序的目的(前提是不利用Sort排序的情况下...

    菩提树下的杨过
  • 利用Boost影响Lucene查询结果的排序

    以下代码在Lucene2.1下通过,主要是通过设置Document的Boost来影响文档的权重,以达到控制查询结果顺序的目的(前提是不利用Sort排序的情况下...

    菩提树下的杨过

扫码关注云+社区

领取腾讯云代金券