正常
Step 3-4:value/progress 解耦 + 平滑过渡
← 手册首页 · 上一步 Step 1-2 环与弧 · 下一步 Step 5-6 配色与兜底 →
Step 3:把 value 和 progress 拆成两个属性
目标
现在 progress 是临时算的(value/100.0)。这一步把它升级成独立的 Q_PROPERTY,和 value 分开。两个成员:value_(0..100,业务值)和 progress_(0..1,动画产物),paintEvent 只认 progress_。
提示
- 头文件加两个 Q_PROPERTY:
value(READ/WRITE/NOTIFY)和progress(READ/WRITE/NOTIFY) progress的 WRITE 必须是纯赋值的setDisplayProgress(double):夹到 [0,1] → 赋给progress_→ emit →update()。不要在这里启动画setValue(int)是业务入口:改value_、emit valueChanged,然后(下一步)启动动画- 想清楚为什么拆:如果 progress 的 WRITE 指向 setValue,动画驱动 setValue、setValue 又启动画——栈溢出。拆开才安全
检查点
setDisplayProgress(0.6) 后弧铺 60%、中间显 "60%";value() 和 progress() 能分别取到 = 解耦对了。这时候 setValue 还没接动画,setValue 后弧会突变——正常,下一步修。
属性系统不熟?Qt 属性系统。
对照答案
- 两个 Q_PROPERTY 声明:
include/circle_progress.h:29-30 value_/progress_成员:include/circle_progress.h:79-80- setDisplayProgress(纯赋值+emit+update):
src/circle_progress.cpp:77
Step 4:QPropertyAnimation 让弧平滑铺开
目标
setValue 不再突变,而是 400ms OutCubic 把弧从当前显示进度接力铺到新进度。
提示
- 成员加
QPropertyAnimation* progress_anim_,构造时new QPropertyAnimation(this, "progress", this)——parent=this 对象树托管,不用 DeleteWhenStopped - 构造里设
setDuration(400)+setEasingCurve(QEasingCurve::OutCubic) - setValue 里三件套:
progress_anim_->stop()→setStartValue(progress_)(当前显示进度,可能是上次动画中间值)→setEndValue(value/100.0)→start() - 关键是
setStartValue(progress_)用当前进度,不是 0、也不是旧 value。这样连点 setValue 弧不会跳回旧目标 - progress_anim_ 是持久指针,反复 stop()/重配/start() 复用,不每次 new
检查点
setValue(60) 后弧花 ~0.4 秒平滑铺到 60%;在动画中途再 setValue(20),弧从当前中间位置接力往 20% 收(不跳回 100% 再下来)= 接力逻辑对了。
对照答案
- 动画对象初始化(持久指针、parent=this):
src/circle_progress.cpp:47 - setValue 的 stop/接力/start 三件套:
src/circle_progress.cpp:55