任务倒计时App

设计背景

在某一阶段可能需要给自己设置长期任务,比如找工作、考研等,需要一个单纯的任务计时工具,设置完任务的目标时间后,每次打开App时都能直接看到最新的剩余时间

设计步骤

1. 写java源码

由于需要界面显示,需要用到swing库等,以下是源码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.List;public class CountdownTimer extends JFrame {private JTextField taskNameField;private JTextField dateTimeField;private JLabel messageLabel;private static final String FILE_PATH = "tasks.txt";private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");private List<Task> tasks = new ArrayList<>();private JPanel tasksPanel;public CountdownTimer() {setTitle("倒计时器");setSize(600, 400);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);// 创建输入框和按钮taskNameField = new JTextField(10);dateTimeField = new JTextField(20);messageLabel = new JLabel("输入任务名和目标时间 (yyyy-MM-dd HH:mm:ss)", SwingConstants.CENTER);JButton addButton = new JButton("添加任务");// 添加事件监听器addButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {addTask();}});// 布局setLayout(new BorderLayout());JPanel inputPanel = new JPanel();inputPanel.add(new JLabel("任务名:"));inputPanel.add(taskNameField);inputPanel.add(new JLabel("目标时间:"));inputPanel.add(dateTimeField);inputPanel.add(addButton);tasksPanel = new JPanel();tasksPanel.setLayout(new BoxLayout(tasksPanel, BoxLayout.Y_AXIS));add(inputPanel, BorderLayout.NORTH);add(new JScrollPane(tasksPanel), BorderLayout.CENTER);add(messageLabel, BorderLayout.SOUTH);// 读取并启动倒计时loadTasks();}private void addTask() {String taskName = taskNameField.getText();String targetDateTimeStr = dateTimeField.getText();try {LocalDateTime targetDateTime = LocalDateTime.parse(targetDateTimeStr, formatter);Task task = new Task(taskName, targetDateTime);tasks.add(task);saveTasks();displayTasks();taskNameField.setText("");dateTimeField.setText("");messageLabel.setText("任务添加成功!");} catch (Exception ex) {messageLabel.setText("请输入正确的日期时间格式: yyyy-MM-dd HH:mm:ss");}}private void displayTasks() {tasksPanel.removeAll();for (Task task : tasks) {JPanel taskPanel = new JPanel(new BorderLayout());JLabel taskLabel = new JLabel();taskPanel.add(taskLabel, BorderLayout.CENTER);JButton deleteButton = new JButton("删除");deleteButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {tasks.remove(task);saveTasks();displayTasks();}});taskPanel.add(deleteButton, BorderLayout.EAST);tasksPanel.add(taskPanel);startTimer(task, taskLabel);}tasksPanel.revalidate();tasksPanel.repaint();}private void startTimer(Task task, JLabel taskLabel) {java.util.Timer timer = new java.util.Timer();timer.scheduleAtFixedRate(new java.util.TimerTask() {@Overridepublic void run() {LocalDateTime now = LocalDateTime.now();long seconds = ChronoUnit.SECONDS.between(now, task.getTargetDateTime());if (seconds <= 0) {taskLabel.setText("<html>" + task.getName() + ": <font size='5'>时间到了!</font></html>");timer.cancel();} else {long years = ChronoUnit.YEARS.between(now, task.getTargetDateTime());now = now.plusYears(years);long months = ChronoUnit.MONTHS.between(now, task.getTargetDateTime());now = now.plusMonths(months);long days = ChronoUnit.DAYS.between(now, task.getTargetDateTime());now = now.plusDays(days);long hours = ChronoUnit.HOURS.between(now, task.getTargetDateTime());now = now.plusHours(hours);long minutes = ChronoUnit.MINUTES.between(now, task.getTargetDateTime());now = now.plusMinutes(minutes);long secs = ChronoUnit.SECONDS.between(now, task.getTargetDateTime());String timeText = String.format("%d年 %d月 %d天 %02d小时 %02d分 %02d秒",years, months, days, hours, minutes, secs);// Pad numbers with zeros to ensure stable layoutString paddedTimeText = timeText.replaceAll("\\b(\\d)\\b", "0$1");// Format the time text with HTML tags to set different font sizesString formattedText = "<html>" + task.getName() + ": ";formattedText += "<font size='5'>" + paddedTimeText + "</font></html>";taskLabel.setText(formattedText);}}}, 0, 1000);}private void saveTasks() {try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_PATH))) {for (Task task : tasks) {writer.write(task.getName() + ";" + task.getTargetDateTime().format(formatter));writer.newLine();}} catch (IOException e) {e.printStackTrace();}}private void loadTasks() {tasks.clear();try (BufferedReader reader = new BufferedReader(new FileReader(FILE_PATH))) {String line;while ((line = reader.readLine()) != null) {String[] parts = line.split(";");if (parts.length == 2) {String taskName = parts[0];LocalDateTime targetDateTime = LocalDateTime.parse(parts[1], formatter);tasks.add(new Task(taskName, targetDateTime));}}displayTasks();} catch (IOException e) {messageLabel.setText("尚未设置任务。");}}public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {new CountdownTimer().setVisible(true);}});}
}class Task {private String name;private LocalDateTime targetDateTime;public Task(String name, LocalDateTime targetDateTime) {this.name = name;this.targetDateTime = targetDateTime;}public String getName() {return name;}public LocalDateTime getTargetDateTime() {return targetDateTime;}
}

2. 将java源码转为jar文件

  JAR文件是一种软件包文件格式,通常用于聚合大量的Java类文件、相关的元数据和资源(文本、图片等)文件到一个文件,以便开发Java平台应用软件或库。
  将源码转为jar文件具体可参考这篇博客:如何将.java文件转为.jar

3. 使用launch4j工具将jar文件转为exe可执行文件

具体步骤可参考这篇博客:luanch4j转exe

App展示

这是App的界面演示
在这里插入图片描述
App自取链接:https://pan.baidu.com/s/1C5Nc5ZsdFsSVU3-SEEsdVA
提取码:dddd

开机自启动

若是想开机直接能看到程序启动,
1.记好转好的jar文件地址
2. 用记事本写一个文件,内容为: java -jar “jar文件的地址” ,随后将文件后缀改为.bat
3. win+R打开运行窗口,输入shell:startup,打开开机自启动文件夹,将前面得到的.bat文件放入这个文件夹中即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/347119.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言 | 使用最简单方法添加显著性ggpubr包

本期教程原文&#xff1a;使用最简单方法添加显著性ggsignif包 本期教程 获得本期教程代码和数据&#xff0c;在后台回复关键词&#xff1a;20240605 小杜的生信笔记&#xff0c;自2021年11月开始做的知识分享&#xff0c;主要内容是R语言绘图教程、转录组上游分析、转录组下游…

五年React手,竟被一个用Ruoyi的Java佬给秒了,这不完了么

被秒了 一个Java摸鱼手&#xff0c;随便用用若依就搞出来一个交互良好&#xff0c;功能强大的管理后台&#xff0c;这让我这个一直用React写管理后台的前端工&#xff0c;很尴尬啊&#xff0c;一下就变小丑了&#xff0c;不行我得抗一波线&#xff0c;用React好好写一个既能对…

如何愉快地实施数仓模型,对比下厨做饭

一般我们建设数仓&#xff0c;有一个链路&#xff1a; 比如这样的 数据从原始层到DWD、DWS层、然后ADS层。 嘿&#xff0c;未来的大数据专家们&#xff01;当我们开始实施数据模型时&#xff0c;不妨参考《大数据之路》这本宝藏书。 让我们一起简化流程&#xff0c;注重细节…

万界星空科技定制化MES系统,实现数字化生产

一、MES生产管理系统强调三个方面&#xff1a; 1、MES是对整个车间制造过程的优化&#xff0c;而不是单一的解决某个生产瓶颈。 2、MES必须提供实时收集生产过程中数据的功能&#xff0c;并作出相应的分析和处理。 3、MES需要与计划层和控制层进行信息交互&#xff0c;通过企业…

项目-基于LangChain的ChatPDF系统

问答系统需求文档 一、项目概述 本项目旨在开发一个能够上传 PDF 文件&#xff0c;并基于 PDF 内容进行问答互动的系统。用户可以上传 PDF 文件&#xff0c;系统将解析 PDF 内容&#xff0c;并允许用户通过对话框进行问答互动&#xff0c;获取有关 PDF 文件内容的信息。 二、…

Linux - 深入理解/proc虚拟文件系统:从基础到高级

文章目录 Linux /proc虚拟文件系统/proc/self使用 /proc/self 的优势/proc/self 的使用案例案例1&#xff1a;获取当前进程的状态信息案例2&#xff1a;获取当前进程的命令行参数案例3&#xff1a;获取当前进程的内存映射案例4&#xff1a;获取当前进程的文件描述符 /proc中进程…

【Linux】信号(二)

上一章节我们进行了信号产生的讲解。 本节将围绕信号保存展开。 目录 信号保存&#xff1a;信号的一些概念&#xff1a;关于信号保存的接口&#xff1a;sigset_t的解释&#xff1a;对应的操作接口&#xff1a;sigprocmask&#xff1a;sigpending&#xff1a;代码实践&#xf…

怎么将3d的模型同比例缩放?---模大狮模型网

在展览3d模型设计过程中&#xff0c;经常需要对3d模型进行缩放以满足不同的需求。然而&#xff0c;有时候缩放操作可能会导致模型失去比例&#xff0c;造成不必要的麻烦。模大狮将介绍如何将展览3D模型按比例缩放&#xff0c;帮助展览设计师们更好地掌握这一关键的模型设计技巧…

我要成为算法高手-双指针篇

目录 什么是双指针?问题1&#xff1a;移动零问题2&#xff1a;复写零问题3&#xff1a;快乐数问题4&#xff1a;盛最多水的容器问题5&#xff1a;有效三角形个数问题6&#xff1a;查找总价格和为目标值的两个商品(两数之和)问题7&#xff1a;三数之和问题8&#xff1a;四数之和…

德克萨斯大学奥斯汀分校自然语言处理硕士课程汉化版(第六周) - 预训练模型

预训练模型 1. 预训练模型介绍 1.1. ELMo1.2. GPT1.3. BERT 2. Seq2Seq 2.1. T52.2. BART 3. Tokenization 1. 预训练模型介绍 在预训练语言模型出现之前&#xff0c;统计语言模型&#xff08;如N-gram模型&#xff09;是主流方法。这些模型利用统计方法来预测文本中的下一个…

Docker系列.Docker Desktop中如何启用Kubernetes

Docker技术概论 Docker Desktop中如何启用Kubernetes - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.…

【wiki知识库】06.文档管理接口的实现--SpringBoot后端部分

目录 一、&#x1f525;今日目标 二、&#x1f388;SpringBoot部分类的添加 1.调用MybatisGenerator 2.添加DocSaveParam 3.添加DocQueryVo 三、&#x1f686;后端新增接口 3.1添加DocController 3.1.1 /all/{ebokId} 3.1.2 /doc/save 3.1.3 /doc/delete/{idStr} …

嵌入式系统概述

嵌入式系统是为了特定应用而专门构建的计算机系统&#xff0c;其嵌入式软件的架构设计与嵌入式系统硬件组成紧密相关。 1.嵌入式系统发展历程 嵌入式系统的发展大致经历了五个阶段&#xff1a; 第一阶段&#xff1a;单片微型计算机&#xff08;SCM&#xff09;&#xff0c;及…

贷款业务——LPR、APR、IRR

文章目录 LPR&#xff08;Loan Prime Rate&#xff09;贷款市场报价利率APR&#xff08;Annual Percentage Rate&#xff09;年化百分比利率IRR&#xff08;Internal Rate of Return&#xff09;内部收益率 LPR、APR 和 IRR 是三个不同的金融术语&#xff0c;LPR 是一种市场利率…

干货分享!2024年Instagram营销必备插件

Instagram是营销人员常用的社交媒体平台&#xff0c;通过提升品牌知名度来推动业务增长。今天给大家分享一些超实用的Instagram营销插件&#xff0c;无论是下载图片视频&#xff0c;还是预先发布帖子&#xff0c;这些工具都可以是你的得力助手&#xff0c;让你的INS运营效率蹭蹭…

Unity2D游戏制作入门 | 12(之人物受伤和死亡的逻辑动画)

上期链接&#xff1a;Unity2D游戏制作入门 | 11(之人物属性及伤害计算)-CSDN博客 上期我们聊到了人物的自身属性和受伤时的计算&#xff0c;我们先给人物和野猪挂上属性和攻击属性的代码&#xff0c;然后通过触发器触发受伤的事件。物体&#xff08;人物也好敌人也行&#xff…

如何使用免费的 Instant Data Scraper快速抓取网页数据

Instant Data Scraper 是一款非常简单易用的网页数据爬虫工具&#xff0c;你不需要任何代码知识&#xff0c;只需要点几下鼠标&#xff0c;就可以把你想要的数据下载到表格里面。以下是详细的使用步骤&#xff1a; 第一步&#xff1a;安装 Instant Data Scraper 打开谷歌浏览…

基于蚁群算法的二维路径规划算法(matlab)

微♥关注“电击小子程高兴的MATLAB小屋”获得资料 一、理论基础 1、路径规划算法 路径规划算法是指在有障碍物的工作环境中寻找一条从起点到终点、无碰撞地绕过所有障碍物的运动路径。路径规划算法较多&#xff0c;大体上可分为全局路径规划算法和局部路径规划算法两大类。其…

js之简单轮播图

今天给大家封装一个简单的轮播图,可以点击下一张上一张以及自动轮播 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>走马…

catia零件装配中通过指南针移动零件

1 将零件导入进来后 2 把指南针移动到零件上 具体移动哪个可以通过模型树点击选中&#xff0c;选中那个就可以移动那个。 这种情况需要注意的是 需要双击选择要移动零件的父节点 如下图&#xff0c;Product2蓝色表示是激活的&#xff0c;这样才可以单击选中下面的零件后通过…