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();
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM