定时闹钟预览版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();
}
}

Java 实现一个带提醒的定时器的更多相关文章

  1. 用java构造一个带层次的文件目录遍历器

    import java.util.List; import java.io.File; import java.util.ArrayList; public class IteratorUtil { ...

  2. DIY一个高大上带提醒的计时器,简单实用,你还在等什么

    小编心语:锵锵锵!小编我又来了!昨天发了一篇比较实用的<Python聊天室>,鉴于反响还不错,SO ,小编也想给大家多分享点有用的干货,让大家边学边用.好了,闲话不多说,今天要给各位看官们 ...

  3. Java基础---Java---IO流-----File 类、递归、删除一个带内容的目录、列出指定目录下文件夹、FilenameFilte

    File 类 用来将文件或者文件夹封装成对象 方便对文件与文件夹进行操作. File对象可以作为参数传递给流的构造函数 流只用操作数据,而封装数据的文件只能用File类 File类常见方法: 1.创建 ...

  4. java中不带package和带package的编译运行方式

    Java中不带package的程序和带package的程序编译的方式是不同的. 一.不带package的程序建立个HelloWorld.java的文件,放入C:\,内容如下:public class ...

  5. 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小

    原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...

  6. Java线程池带图详解

    线程池作为Java中一个重要的知识点,看了很多文章,在此以Java自带的线程池为例,记录分析一下.本文参考了Java并发编程:线程池的使用.Java线程池---addWorker方法解析.线程池.Th ...

  7. 面试:用 Java 实现一个 Singleton 模式

    面试:用 Java 实现一个 Singleton 模式 面试系列更新后,终于迎来了我们的第一期,我们也将贴近<剑指 Offer>的题目给大家带来 Java 的讲解,个人还是非常推荐< ...

  8. File类_删除一个带内容的目录_练习

    需求:删除一个带内容的目录 原理:必须从最里面往外删除需要深度遍历 import java.io.File; public class RemoveDirTest { public static vo ...

  9. Java发邮件带附件测试通过

    package cn.bric.crm.util; import java.util.Date; import java.util.Enumeration; import java.util.Prop ...

随机推荐

  1. Python语法糖

    1.装饰器 ####装饰器的固定格式 ##普通版本 def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' ret = func(*ar ...

  2. HTML中footer固定在页面底部的若干种方法

    <div class="header"><div class="main"></div></div> <d ...

  3. 虚拟内存设置(解决linux内存不够情况)

    一.      虚拟内存介绍 背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级.所以,程序和数据如果在内存的话,会有非常快的读写速度.但是,内存的造价是要高于 ...

  4. DevOps - 版本控制 - Bitbucket

    Bitbucket 使用139邮箱无法收到注册邮件 https://bitbucket.org

  5. 精干货! Java 后端程序员 1 年工作经验总结

    一.引言   毕业已经一年有余,这一年里特别感谢技术管理人员的器重,以及同事的帮忙,学到了不少 东西.这一年里走过一些弯路,也碰到一些难题,也受到过做为一名开发却经常为系统维护 和发布当救火队员的苦恼 ...

  6. 迷你MyBank

    该迷你MyBank,存贮是用对象数组来存贮的,所以比较简单,容易理解,适合新手.. 一.创建chengyuan类,在其中声明所需的成员变量: public class chengyuan { //该类 ...

  7. java常见面试问题.你一定会预见到。

    1判断一个char字符是不是数字:Character.isDigit(char).是数字返回true,反之返回false. 2字符串的toCharArray() 把字符串转换为字符数组.返回char[ ...

  8. .net core 发布到docker

    1. 安装docker-desktop,windows环境安装包 官方网站:https://www.docker.com/ 2.注册登陆Docker账号 安装成功后,在官方网站注册一个账号,使用账号登 ...

  9. h5移动端页面meta标签

    <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --> <html lang="zh-cmn-Hans"&g ...

  10. web视频播放

    webm.mp4/h264    video.js hevc libde265.js hls/m3u8 hls.js