Skip to content
正常

卡住怎么办

按症状找,只指方向。答案在成品 widget/range-slider/

手柄画在固定位置 / 不跟着值走

paintEvent 里手柄圆心 x 写死成常量了,没用 valueToX。圆心 x 必须是 valueToX(lower_value_) / valueToX(upper_value_),值变了手柄才挪。对照 range_slider.cpp:287-288,301-302

拖动时手柄飞出轨道 / 越过另一手柄

setter 里没 clamp,直接把 xToValue 的结果写进了成员变量。setLowerValue 要夹到 [minimum_, upper_value_ - gap]setUpperValue 夹到 [lower_value_ + gap, maximum_]。对照 range_slider.cpp:113,126

改完 minimum / maximum 后约束破了(lower 跑到区间外)

端点 setter 只改了 minimum_ / maximum_,没回夹现有 lower_value_ / upper_value_。setter 收尾要把两值重新 std::clamp(minimum_, x, maximum_),值变了补发信号。对照 range_slider.cpp:44-53,69-77

分别 setMinimum / setMaximum 时中间态崩

setMinimum(80)setMaximum(20),第一步之后 minimum > maximum 就已经非法。用 setRange 一次性设两端(反着传会自动 swap),避开中间态。对照 range_slider.cpp:82-104

两手柄重合后点一下抓错手柄

hitTestHandle 在两距离相等时没定优先级,或容差太大导致两个都命中。让 lower 优先(d_lower <= d_upper 时选 lower),且只有真正在容差内才命中。对照 range_slider.cpp:204-209

两手柄重合时区间绘制异常

x_upper == x_lowerdrawRoundedRect 拿到宽度 0 可能退化。区间宽度一律 std::max(0.0, |x_upper - x_lower|)。对照 range_slider.cpp:291

点一下被当成拖动,手柄乱跑

没设移动阈值,手抖就被判拖。mouseMoveEvent 里移动没超过 kDragThreshold(4px)一律不进拖动模式;纯点击走松手吸附。对照 range_slider.cpp:234-237,254-262

窗口缩很窄时崩 / 手柄飞掉

xToValue(x - left) / widthwidth <= 0span <= 0 时除零得 NaN。两个映射函数都得判兜底。对照 range_slider.cpp:181-183,191-193

valueToX 把端点手柄画到控件边界外(圆心越界)

trackRect 没缩进。左右各让出半个手柄直径,端点值的圆心才正好落在轨道两端。对照 range_slider.cpp:172-176

拖动卡顿 / 掉帧

setter 里用了 repaint() 同步重绘,没走事件循环合并。一律 update() 异步重绘。对照 range_slider.cpp:120,133


实在卡死,成品 widget/range-slider/src/range_slider.cpp 就是答案——但先自己拼。

AwesomeQt v0.3.0-2-gbbb418e · bbb418e · 2026-07-12