Java实现一周倒计时GUI:解决界面更新与时间转换难题
问题解决与代码修正
初始需求问题解决
1. 总秒数转「天:时:分:秒」格式
利用TimeUnit工具类分步拆解总秒数,结合格式化补零实现统一格式:
private static String formatSeconds(long totalSeconds) { long days = TimeUnit.SECONDS.toDays(totalSeconds); totalSeconds -= TimeUnit.DAYS.toSeconds(days); long hours = TimeUnit.SECONDS.toHours(totalSeconds); totalSeconds -= TimeUnit.HOURS.toSeconds(hours); long minutes = TimeUnit.SECONDS.toMinutes(totalSeconds); totalSeconds -= TimeUnit.MINUTES.toSeconds(minutes); long seconds = totalSeconds; // 补零保证格式统一,如1天2小时3分4秒显示为01:02:03:04 return String.format("%02d:%02d:%02d:%02d", days, hours, minutes, seconds); }
2. 关联JLabel更新GUI
Swing组件必须在**事件调度线程(EDT)**中修改,需通过SwingUtilities.invokeLater()将更新操作提交到EDT执行,避免线程安全问题。
后续GUI更新问题修正
你当前代码的核心问题:多线程拆分时间逻辑导致不同步、每秒新建GUI实例而非更新现有界面、静态变量引发线程风险。以下是修正后的完整代码:
import java.util.concurrent.*; import javax.swing.*; import static java.util.concurrent.TimeUnit.SECONDS; public class Countdown { private static final long TOTAL_SECONDS = 7 * 24 * 60 * 60; // 1周总秒数 private long remainingSeconds = TOTAL_SECONDS; private final JLabel timerLabel; public Countdown() { // 初始化GUI JFrame frame = new JFrame("Countdown Timer"); timerLabel = new JLabel(formatSeconds(remainingSeconds)); timerLabel.setFont(timerLabel.getFont().deriveFont(24f)); // 放大字体提升可读性 JPanel panel = new JPanel(); panel.add(timerLabel); frame.add(panel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); // 窗口居中显示 frame.setVisible(true); // 启动倒计时任务 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(this::updateTimer, 0, 1, SECONDS); } private void updateTimer() { remainingSeconds--; // 倒计时结束自动重置 if (remainingSeconds < 0) { remainingSeconds = TOTAL_SECONDS; } final String timeText = formatSeconds(remainingSeconds); // 在EDT中安全更新GUI文本 SwingUtilities.invokeLater(() -> timerLabel.setText(timeText)); } private static String formatSeconds(long totalSeconds) { long days = SECONDS.toDays(totalSeconds); totalSeconds -= TimeUnit.DAYS.toSeconds(days); long hours = SECONDS.toHours(totalSeconds); totalSeconds -= TimeUnit.HOURS.toSeconds(hours); long minutes = SECONDS.toMinutes(totalSeconds); totalSeconds -= TimeUnit.MINUTES.toSeconds(minutes); long seconds = totalSeconds; return String.format("%02d:%02d:%02d:%02d", days, hours, minutes, seconds); } public static void main(String[] args) { // 在EDT中启动GUI,符合Swing线程规则 SwingUtilities.invokeLater(Countdown::new); } }
关键改进说明
- 单一倒计时逻辑:用单个任务处理时间计算,避免多线程不同步
- EDT安全更新:所有GUI操作通过
SwingUtilities.invokeLater()提交到EDT - 避免重复实例:仅初始化一次GUI,每次更新仅修改JLabel文本
- 自动循环重置:倒计时结束后自动恢复为1周时长
- 格式统一:通过格式化补零保证时间显示美观规范
内容的提问来源于stack exchange,提问作者Mute
相关产品推荐
相关产品推荐

