
Java Swing 里用 Timer 还是 Thread 做倒计时刷新?
倒计时壁纸本质是「每秒重绘一次窗口」,不是高帧率动画,别上 Thread.sleep() + 死循环。Swing 是单线程 GUI 框架,所有 UI 更新必须在 Event Dispatch Thread(EDT)做,否则画面撕裂、组件不响应、甚至直接崩溃。
正确做法是用 javax.swing.Timer,它自动把任务投递回 EDT,安全又省心。用 java.util.Timer 或裸 Thread 启动 repaint(),大概率触发 IllegalStateException: must be called from EDT 或绘图错位。
-
javax.swing.Timer构造时传毫秒间隔(比如1000),动作监听器里调repaint()即可 - 别在
paintComponent()里算时间差——那里只负责绘图,逻辑放 Timer 的actionPerformed()里 - 启动前记得
timer.start(),暂停用timer.stop(),别漏掉
怎么让壁纸背景不被窗口边框遮住?
Java 默认 JFrame 有标题栏和边框,倒计时数字画在客户区,但“壁纸”效果要求全屏无边框、穿透系统桌面层级。核心就两点:去掉装饰 + 提升窗口层级。
关键不是“设成全屏”,而是“设成无边框顶层窗口”。用 setUndecorated(true) 干掉标题栏和边框;再用 setAlwaysOnTop(true) 确保不被其他应用盖住;最后用 GraphicsDevice.setFullScreenWindow() 或 setBounds() 拉满整个屏幕。
立即学习“Java免费学习笔记(深入)”;
- 调
setUndecorated(true)必须在setVisible(true)之前,否则抛IllegalComponentStateException - 如果想兼容多屏,别硬写
1920x1080,改用GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds() - Windows 下若发现窗口被任务栏挡住,加一句
setExtendedState(JFrame.MAXIMIZED_BOTH)再配合setLocation(0, 0)
动态绘图时文字模糊、锯齿严重怎么办?
Java 2D 默认抗锯齿关闭,尤其在高分屏或缩放比例非 100% 时,drawString() 出来的数字边缘发虚、有白边。这不是字体问题,是渲染设置没开。
必须在 paintComponent(Graphics g) 开头强转为 Graphics2D,并启用文本和几何图形的抗锯齿:
Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
- 别只设
KEY_ANTIALIASING,它对文字无效,必须单独设KEY_TEXT_ANTIALIASING - 字体大小建议用整数(如
48f),避免小数导致渲染抖动 - 如果用
GradientPaint填充文字,确保颜色过渡区间足够宽,否则高对比下仍显颗粒感
退出程序时倒计时线程没停干净,进程还挂着?
Swing 窗口默认关闭操作是 HIDE_ON_CLOSE,关掉窗口只是隐藏,Timer 和后台资源全活着。用户点右上角 ×,结果进程还在任务管理器里占内存——这是最常被忽略的泄漏点。
必须显式设关闭行为为 EXIT_ON_CLOSE,同时确保 Timer 被 stop(),避免重复启动多个 Timer 实例:
- 在构造完 JFrame 后立刻调
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) - 在
dispose()或窗口监听器的windowClosed()里加if (timer != null && timer.isRunning()) timer.stop() - 如果用了自定义线程(比如读配置、轮询网络时间),务必在
System.exit(0)前调thread.interrupt()并join()
倒计时壁纸的复杂点不在“怎么画”,而在“怎么干净地活、再彻底地死”。窗口层级、线程归属、渲染质量、生命周期这四块,漏掉任何一块,软件就只是能跑,不是能用。










