定时闹钟预览版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. css的基础用法(上)

    css定义: CSS层叠式样表(Cascading  Style Sheets)是一种用来表现html或xml等文件样式的计算机语言.CSS不仅可以静态的修饰网页,还可以配合各种脚本语言动态地对网页个 ...

  2. 轻量ORM-SqlRepoEx (五) 存储过程操作

    .Net平台下兼容.NET Standard 2.0,一个实现以Lambda表达式转转换标准SQL语句,使用强类型操作数据的轻量级ORM工具,在减少魔法字串同时,通过灵活的Lambda表达式组合,实现 ...

  3. js函数只触发一次

    如何让js中的函数只被执行一次?我们有时候会有这种需求,即让一个函数只执行一次,第二次调用不会返回任何有价值的值,也不会报错.下面将通过三个小demo展示使用的方法,当做个人笔记. 1.通过闭包来实现 ...

  4. ABAP术语-Fiscal Year

    Fiscal Year 原文:http://www.cnblogs.com/qiangsheng/archive/2008/02/02/1062109.html Generally a period ...

  5. Zookeeper 面试总结

    1:Zookeeper是什么? 答:ZooKeeper是一个开源的分布式协调服务,是集群的管理者,监视集群节点反馈信息进行下一步合理操作. Zookeeper提供的服务:管理用户程序提交的数据:为用户 ...

  6. JDBC与Statement和PreparedStatement的区别

    一.先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句.具体步骤: 1.首先导入 ...

  7. git merge最简洁

    一.开发分支(dev)上的代码达到上线的标准后,要合并到 master 分支 git checkout devgit pullgit checkout mastergit merge devgit p ...

  8. 浅谈C#实现Web代理服务器的几大步骤

    代理服务程序是一种广泛使用的网络应用程序.代理程序的种类非常多,根据协议不同可以分成HTTP代理服务程序.FTP代理服务程序等,而运行代理服务程序的服务器也就相应称为HTTP代理服务器和FTP代理服务 ...

  9. latex03-LaTeX中的中文处理办法

    编译含中文的tex文件的前提有三个: 默认编译器为XeLaTeX: 编辑器的默认字体编码格式为UTF-8: 引入ctex的宏包. 效果: 源码: %导言区 \documentclass{article ...

  10. SapScript

    * [OPEN_FORM] SAPscript: フォーム印刷の開始 * [START_FORM] SAPscript: 書式を開始 * [WRITE_FORM] SAPscript: 書式ウィンドウ ...