任务倒计时App

设计背景

在某一阶段可能需要给自己设置长期任务,比如找工作、考研等,目前市面上的日历、倒计时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() {
            @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文件地址
2. 用记事本写一个文件,内容为: java -jar “jar文件的地址” ,随后将文件后缀改为.bat
3. win+R打开运行窗口,输入shell:startup,打开开机自启动文件夹,将前面得到的.bat文件放入这个文件夹中即可

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值