Java 實現一個帶提醒的定時器

定時鬧鐘預覽版EXE下載連接:https://files.cnblogs.com/files/rekent/ReadytoRelax_jar.ziphtml


功能說明:

  實現了一個休息提醒器,用戶首先設定一個倒計時時間(HH:MM:SS),每走完這個時間便會彈出提醒,讓用戶中止工做,起身休息。java

  休息回來工做時只需點擊彈窗上的繼續工做即可以繼續以當前時間繼續開始倒計時。api


涉及技術:

  使用相似Timer的定時器來推遲提醒線程的執行即可完成程序的主體部分,再輔以JavaFXAWT來構建GUI界面便可。oracle

  此處使用ScheduledThreadPoolExecutor(點擊此處獲取該線程池的具體用法)這個線程池來實現延時執行的功能。ide


當前涉及的問題:

  點擊開始計時後,沒法中止計時(沒法獲取到線程池中的線程並終止它);函數

  線程池的進程不會由於JavaFX程序的關閉而結束,二者這件沒有相互約束的關係;
spa


源代碼(一):(點擊事件)

    @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便可。rest

    

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();
        }
    }
相關文章
相關標籤/搜索