任务倒计时App

设计背景

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

设计步骤

1. 写java源码

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

java 复制代码
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() {
            @Override
            public 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() {
                @Override
                public 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() {
            @Override
            public 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 layout
                    String paddedTimeText = timeText.replaceAll("\\b(\\d)\\b", "0$1");

                    // Format the time text with HTML tags to set different font sizes
                    String 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() {
            @Override
            public 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文件地址

  1. 用记事本写一个文件,内容为: java -jar "jar文件的地址" ,随后将文件后缀改为.bat

  2. win+R打开运行窗口,输入shell:startup,打开开机自启动文件夹,将前面得到的.bat文件放入这个文件夹中即可

相关推荐
幽络源小助理1 分钟前
微信小程序实验室管理SSM系统设计与实现
微信小程序·小程序
跟着珅聪学java1 小时前
spring boot +Elment UI 上传文件教程
java·spring boot·后端·ui·elementui·vue
我命由我123451 小时前
Spring Boot 自定义日志打印(日志级别、logback-spring.xml 文件、自定义日志打印解读)
java·开发语言·jvm·spring boot·spring·java-ee·logback
lilye661 小时前
程序化广告行业(55/89):DMP与DSP对接及数据统计原理剖析
java·服务器·前端
徐小黑ACG2 小时前
GO语言 使用protobuf
开发语言·后端·golang·protobuf
0白露3 小时前
Apifox Helper 与 Swagger3 区别
开发语言
Tanecious.4 小时前
机器视觉--python基础语法
开发语言·python
叠叠乐4 小时前
rust Send Sync 以及对象安全和对象不安全
开发语言·安全·rust
战族狼魂5 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
Tttian6226 小时前
Python办公自动化(3)对Excel的操作
开发语言·python·excel