You need to enable JavaScript to run this app. 如何使用Java Swing制作支持自定义值的滚动动画数字计数器
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java Swing制作支持自定义值的滚动动画数字计数器

Swing 平台滚轮式动画数字计数器实现指南

核心实现逻辑

完全匹配垂直滚动数字、无生硬跳变的效果,不需要引入第三方依赖,基于Swing原生能力即可搭建,整体逻辑分为三层:

  1. 动画驱动层:使用Swing内置的javax.swing.Timer作为动画帧触发源,按60fps(每16ms一帧)的频率触发UI更新,所有操作都在事件 dispatch 线程(EDT)执行,从根源上避免Swing常见的UI线程安全问题。
  2. 视觉渲染层:把显示的数字拆分为独立的数位滚轮,每个数位单独渲染垂直排列的0-9数字序列,通过调整垂直偏移量实现滚动效果,替代直接替换文本的生硬跳变。
  3. 数值控制层:对外暴露统一的setTargetValue()公开方法,调用时自动记录当前旧值、计算新旧值的差值、启动对应时长的滚动动画,直到数值稳定到目标值后自动停止动画释放资源。

关键实现要点

  • 动画插值:对滚动进度应用ease-out 缓动函数,实现滚动启动快、接近目标值时逐渐减速的效果,和示例里的机械滚轮手感一致,比线性匀速滚动的观感自然很多。
  • 数位自适应:根据目标数值的位数动态增减内部的数位滚轮数量,比如从99变到100时自动补出百位的滚轮,不需要手动固定最大显示位数。
  • 边界裁剪:给每个数位滚轮设置固定的可视区域大小,渲染时只显示当前偏移量对应的单个数字,避免滚动过程中相邻数字溢出到可视区造成视觉混乱。
  • 样式统一:使用等宽字体渲染所有数字,保证每个数位的宽度固定,不会因为数字本身的宽度差异导致布局抖动。

核心参考代码片段

// 60fps 动画定时器,所有回调运行在EDT线程
Timer rollTimer = new Timer(16, e -> {
    // 计算当前动画进度,范围0~1
    float progress = Math.min(currentFrame / totalFrames, 1.0f);
    // 三次方缓动,实现滚动到目标值时逐渐减速的效果
    float easedProgress = 1 - (float)Math.pow(1 - progress, 3);
    // 更新每个滚轮的垂直偏移并触发重绘
    rollerList.forEach(roller -> roller.updateOffset(easedProgress));
    repaint();
    // 动画播放完成后停止定时器,避免资源空耗
    if (progress >= 1) {
        ((Timer) e.getSource()).stop();
    }
});

常见踩坑提醒

  • 不要在自定义业务线程中直接修改UI组件状态,更不要在EDT中使用Thread.sleep()做帧延时,会直接导致整个Swing界面卡死无响应。
  • 绘制数字时开启文本抗锯齿,避免滚动过程中数字边缘发虚、出现锯齿残影。
  • 提前为数字设置合适的上下留白,不然滚动过程中数字的上下边缘会被可视区域裁切,影响观感。

内容的提问来源于stack exchange,提问作者Chauncey Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.15 02:45:05