一、项目简介
功能描述:该计时器应用程序允许用户输入一个计时器的名称和倒计时时间,并启动、停止和重置计时器。当用户启动计时器时,程序会启动一个单独的线程来执行倒计时功能,并在文本框中显示剩余时间。当时间减少到0时,计时器将停止,并且所有按钮将被设置为可用状态,以便用户重新设置计时器。此外,该应用程序还包括一些逻辑,用于验证用户输入的时间格式,并在需要时显示错误消息。总之,该计时器应用程序提供了一个简单但实用的计时器,可以用于各种计时需求。
个人负责任务:
- 设计和实现了计时器应用程序的功能,包括用户界面、计时器线程、事件处理程序和计算器逻辑。
- 使用Java编程语言和Swing GUI库来创建用户界面和实现计时器功能。
- 实现了一个简单但实用的计时器应用程序,可以用于各种计时需求。
二、功能架构图
三、个人任务简述
1. 完成的任务与功能:
简单描述将自己完成的有特色的地方、重难点地方。
序号 | 完成功能与任务 | 描述 |
1 | 倒计时功能 | 线程、事件处理程序和计算器逻辑完成了基本的倒计时功能。 |
2 | 面向对象设计 | 使用了面向对象技术设计系统。 |
3 | 记录功能 | 创建了一个JTextArea用于记录倒计时的基本信息。 |
四、本人负责功能详解
1.用户界面模块:
该模块负责创建用户界面,包括一个文本框用于输入倒计时时间、一个标签用于显示计时器名称、一个按钮用于启动计时器、一个按钮用于停止计时器以及一个按钮用于重置计时器。用户可以在文本框中输入倒计时时间,然后单击“Start”按钮启动计时器,或单击“Stop”按钮停止计时器,或单击“Reset”按钮重置计时器。该模块使用Swing GUI库来创建用户界面。
2.计时器模块:
该模块负责实现计时器功能,包括启动、停止和重置计时器。当用户单击“Start”按钮时,该模块会启动一个单独的线程来执行倒计时功能,每秒钟减少一秒的时间,并将剩余时间显示在文本框中。当时间减少到0时,计时器将停止,并将所有按钮设置为可用状态,以便用户重新设置计时器。当用户单击“Stop”按钮时,计时器将被停止。当用户单击“Reset”按钮时,计时器将被重置为最初的时间,并将所有按钮设置为可用状态。
3.事件处理模块:
该模块负责处理用户的事件,包括单击“Start”按钮、单击“Stop”按钮和单击“Reset”按钮等事件。当用户单击“Start”按钮时,事件处理程序将启动计时器模块,并根据用户输入的时间来启动计时器线程。当用户单击“Stop”按钮时,事件处理程序将停止计时器模块。当用户单击“Reset”按钮时,事件处理程序将重置计时器模块并将所有按钮设置为可用状态。
4.计算逻辑模块:
该模块负责验证用户输入的时间格式,并在需要时显示错误消息。它还包括一些逻辑,用于将计时器线程的状态设置为运行、停止或重置。
五、课程设计感想
这个计时器核心的计时算法有三个版本,第一个版本使用System.currentTimeMillis()方法直接调取系统时间,换算后进行显示、计时等等操作,但这个版本完全没有技术含量,所以放弃了。第二个版本则创建了两个线程tCh与t1,tCh同样调用System.currentTimeMillis()方法进行毫秒的计算,当tCh完成了1000毫秒计时后,给t1线程内一个布尔变量设为true,t1再进行秒、分钟等等计算,但由于多线程未做好同步,第二个版本便放弃
六、展望
1.不足:目前对于线程同步还是不熟悉,并且这个版本的计时器仍有一些小bug,需要学习的东西还有很多。
2.展望:第二个版本只要能够做好数据同步的话其实是最好的,因此未来当然打算继续学习一些多线程、数据同步相关的知识,把第二个版本完善好。
package TimerSe;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TimerSec extends JFrame implements ActionListener {
private JTextField nameField, timeField;
private JTextArea logArea;
private JButton startButton, stopButton, resetButton;
private int minutes = 0, seconds = 0, mminutes = 0, mseconds = 0;
private boolean running = false;
public TimerSec() {
setTitle("Timer");
setSize(400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation((1920 - 800) / 2, (1080 - 600) / 2);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(5, 2));
JLabel nameLabel = new JLabel("Name:");
nameField = new JTextField();
JLabel timeLabel = new JLabel("Time (mm:ss):");
timeField = new JTextField();
logArea = new JTextArea(5, 20);
logArea.setEditable(false);
startButton = new JButton("Start");
startButton.addActionListener(this);
stopButton = new JButton("Stop");
stopButton.addActionListener(this);
resetButton = new JButton("Reset");
resetButton.addActionListener(this);
panel.add(nameLabel);
panel.add(nameField);
panel.add(timeLabel);
panel.add(timeField);
panel.add(new JLabel());
panel.add(new JLabel());
panel.add(startButton);
panel.add(stopButton);
panel.add(resetButton);
panel.add(new JLabel());
getContentPane().add(panel, BorderLayout.NORTH);
getContentPane().add(new JScrollPane(logArea), BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == startButton) {
if (!running) {
try {
minutes = Integer.parseInt(timeField.getText().split(":")[0]);
seconds = Integer.parseInt(timeField.getText().split(":")[1]);
mminutes = minutes;
mseconds = seconds;
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Invalid time format. Please enter mm:ss.");
return;
}
if (minutes < 0 || seconds < 0 || seconds >= 60) {
JOptionPane.showMessageDialog(null, "Invalid time format. Please enter mm:ss.");
return;
}
running = true;
startButton.setEnabled(false);
stopButton.setEnabled(true);
resetButton.setEnabled(false);
nameField.setEditable(false);
timeField.setEditable(false);
logArea.append(nameField.getText() + ": " + minutes + " minutes " + seconds + " seconds\n");
Thread t1 = new Thread(new Runnable() {
public void run() {
while (running && minutes >= 0 && seconds >= 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (seconds == 0) {
if (minutes == 0) {
running = false;
startButton.setEnabled(true);
stopButton.setEnabled(false);
resetButton.setEnabled(true);
nameField.setEditable(true);
timeField.setEditable(true);
break;
} else {
minutes--;
seconds = 59;
}
} else {
seconds--;
}
timeField.setText(String.format("%02d:%02d", minutes, seconds));
}
}
});
t1.start();
}
} else if (source == stopButton) {
running = false;
startButton.setEnabled(true);
stopButton.setEnabled(false);
resetButton.setEnabled(true);
nameField.setEditable(true);
timeField.setEditable(true);
} else if (source == resetButton) {
running = false;
minutes = mminutes;
seconds = mseconds;
timeField.setText(String.format("%02d:%02d", minutes, seconds));
startButton.setEnabled(true);
stopButton.setEnabled(false);
resetButton.setEnabled(false);
nameField.setEditable(true);
timeField.setEditable(true);
}
}
}
package TimerSe;
public class Run {
public static void main(String[] args) {
TimerSec TimerSec = new TimerSec();
TimerSec.setVisible(true);
}
}