面板限高与滚动改造 + 边沿统计不再卡在“统计中…” + 组名折起真正收起
一、浮动面板(用户报告:下方空白、滚动时画到面板外、未改造的面板让一切交互卡顿) 1. ⭐ 根因:旧「逐条目」排布没有高度上限 —— 288 条信号时面板 13010px(绘图区 846px) ⇒ PanelRectInsideLayer 恒假 ⇒ 面板像素缓存一次都存不进去 ⇒ 每帧整块重画。 现在 5 个面板全部限高 + 可滚动,旧的 itemized 布局/绘制/交互整体删除。 2. 无按钮面板(中心轴边沿计数)不再预留「按钮行 + pad」⇒ 底部空白 55px → 8.8px(1 个 pad)。 3. ⚠️ 统计文字改用 UiTextClipped:GDI 文本不受 GDI+ SetClip 约束,滚动时画到标题栏之外。 4. 「弱峰调整」改造为与均值滤波同款的分组列表(条目栏 + 右侧复选框 + 展开后的两行滑块 + 复位按钮 + 底部「构建为新信号」);新增 Lane::weakPeakScroll / SetLaneWeakPeakScroll, WeakPeakItem 增加 collapsed。 5. 「边沿计数」保留两行排版,但内容区同样限高、可滚动(新增 Lane::edgeCountScroll)。 6. 鼠标指针:列表式面板的条目栏**只有已勾选**才显示手型(未勾选点击无效果,保持箭头); 参数行控件只在参数行展开时给手型 / 左右箭头。 7. 内部标志 m_meanDragCenter / m_editMeanCenter(bool)改为 m_meanDragKind / m_editMeanKind (EdgePanelKind),以便 MEAN / CENTER / PEAK / COUNT 共用同一套滚动与滑块拖拽。 二、边沿统计“全部统计中…且永不更新”(288 信号合并到同一网格) 1. ⭐ 根因:累积状态上限固定 64 < 信号数 288 ⇒ 新建状态总淘汰未完成的 ⇒ 没有任何状态能扫完。 新增 EdgeScanStateLimit() = max(64, 全部信号数 × 2 + 16)。 2. 去掉每状态 60000 的固定配额下限(状态一多就把整帧预算耗光),改为 budget / 未完成状态数; 分母只数未完成状态,短信号扫完后立刻把预算让给长信号。 三、组名折起后“三角已收起但信号行仍在、仍可点选” 1. ⭐ 根因:RequestEdgeScanFrame() 在每个未完成状态里各 Post 一次(单帧最多 288 次), 把优先级最低的 WM_TIMER 饿死 ⇒ AdvanceGroupAnimations 永不执行 ⇒ 折起动画永不结束。 修法:每帧最多 Post 一次(m_edgeScanRequestFrame)。 2. 另一道保险:SignalPanel::EnsureRows() 开头推进一次动画 —— 动画进度只依赖挂钟时间, 不依赖消息能否按时到达。 四、验证(离屏探针 .preflight/p20,全部 SW_HIDE + 合成消息,不占用鼠标/键盘/屏幕) p20.exe 9/9:面板限高且像素缓存真的写进去了、288 个统计全部 complete、中心轴面板底部留白、 组名折起后行集合无该组信号、两组都折起后 signalRows == 0(真实消息 + WM_TIMER)。 p20c.exe 11/11:弱峰面板限高/可滚动/缓存命中、展开与收起、滚动生效、条目栏手型规则、 中心轴滚动时标题栏 0 像素变化(A/B 关掉裁剪 ⇒ 805px)、288 信号空闲帧 2.6ms。 make release / make debug 零 warning。
This commit is contained in:
1 parent
334015c1a9
commit
7a6fcd68e2
9 files changed
+914
-795
No files matched your search
@@ -1103,6 +1103,21 @@ namespace jdi
|
||||
*/
|
||||
bool SetLaneEdgeCenterScroll(int laneIndex, float scroll);
|
||||
|
||||
/**
|
||||
* @brief 设置某网格「弱峰调整」面板内容的滚动偏移(客户区像素,0 = 顶部)。
|
||||
* @return 偏移真的发生变化返回 true。
|
||||
*/
|
||||
bool SetLaneWeakPeakScroll(int laneIndex, float scroll);
|
||||
|
||||
/**
|
||||
* @brief 设置某网格「边沿计数」面板内容的滚动偏移(客户区像素,0 = 顶部)。
|
||||
*
|
||||
* 该面板仍是旧式「每信号两行」排版,但内容可以滚动:上百个信号合并到同一网格时
|
||||
* 内容高达上万像素,不限高会让面板远超绘图区(面板像素缓存因此完全失效)。
|
||||
* @return 偏移真的发生变化返回 true。
|
||||
*/
|
||||
bool SetLaneEdgeCountScroll(int laneIndex, float scroll);
|
||||
|
||||
/**
|
||||
* @brief 切换某网格「自由标记」面板里某个信号分组的收起状态。
|
||||
* @return 切换后为「已收起」返回 true。
|
||||
@@ -2814,13 +2829,15 @@ namespace jdi
|
||||
int m_meanDragLane = -1; /**< 正在拖动「均值滤波」参数滑块的面板所属网格。 */
|
||||
SignalRef m_meanDragRef; /**< 正在拖动「均值滤波」参数滑块的信号(每信号一套参数)。 */
|
||||
/**
|
||||
* @brief 当前参数滑块拖拽的目标是**中心轴边沿计数**面板(而不是均值滤波)。
|
||||
* @brief 当前「列表式面板」参数滑块 / 滚动条拖拽的目标面板种类。
|
||||
*
|
||||
* 「中心轴边沿计数」自 2026-11-02 起与「均值滤波」共用同一套可滚动列表与滑块交互,
|
||||
* 因此复用 `MEAN_POINTS` / `MEAN_ITERATIONS` / `MEAN_SCROLL` 三个拖拽模式;
|
||||
* 这个标志说明它们的写入目标是 `Lane::edgeCenterItems` 还是 `Lane::meanFilterItems`。
|
||||
* 「均值滤波」「中心轴边沿计数」「弱峰调整」自 2026-11-02 起共用同一套**可滚动列表**
|
||||
* (信号色叠底条目栏 + 右侧复选框 + 展开后的参数滑块)与同一套拖拽模式
|
||||
*(`MEAN_POINTS` / `MEAN_ITERATIONS` / `MEAN_SCROLL`);本字段说明它们的写入目标是
|
||||
* `Lane::meanFilterItems` / `edgeCenterItems` / `weakPeakItems` 中的哪一个。
|
||||
* 「边沿计数」面板(旧式两行排版)也用它区分滚动目标。
|
||||
*/
|
||||
bool m_meanDragCenter = false;
|
||||
EdgePanelKind m_meanDragKind = EdgePanelKind::MEAN;
|
||||
/**
|
||||
* @brief 正在编辑「均值滤波」某个滑块上限时,输入框内灰色提示用的**当前上限值**。
|
||||
*
|
||||
@@ -2829,12 +2846,13 @@ namespace jdi
|
||||
int m_meanEditCurrentMax = 0;
|
||||
|
||||
/**
|
||||
* @brief 正在编辑「滑块上限」的是**中心轴边沿计数**面板(而不是均值滤波)。
|
||||
* @brief 正在编辑「滑块上限」的目标面板种类(均值滤波 / 中心轴边沿计数)。
|
||||
*
|
||||
* 与 `m_meanDragCenter` 同一思路:两者共用 `MEAN_POINTS_MAX` / `MEAN_ITERATIONS_MAX`
|
||||
* 两个编辑目标,这个标志说明提交时要写到 `Lane::edgeCenterItems` 还是 `meanFilterItems`。
|
||||
* 与 `m_meanDragKind` 同一思路:两者共用 `MEAN_POINTS_MAX` / `MEAN_ITERATIONS_MAX`
|
||||
* 两个编辑目标,本字段说明提交时要写到 `Lane::edgeCenterItems` 还是 `meanFilterItems`。
|
||||
* 「弱峰调整」仍用自己的 `PEAK_ITERATIONS_MAX` 与 `m_peakEditCurrentMax`。
|
||||
*/
|
||||
bool m_editMeanCenter = false;
|
||||
EdgePanelKind m_editMeanKind = EdgePanelKind::MEAN;
|
||||
/**
|
||||
* @brief 正在编辑「迭代次数 N 上限」时,输入框内灰色提示用的**当前上限值**。
|
||||
*
|
||||
@@ -3061,9 +3079,25 @@ namespace jdi
|
||||
* 用户看到的就是“按住光标不动时统计卡住、要动鼠标才更新”。
|
||||
*/
|
||||
mutable std::uint64_t m_edgeScanFrame = 0;
|
||||
/**
|
||||
* @brief 上一次“请求下一帧”发生在哪一帧(收敛成**每帧最多一次** `PostMessage`)。
|
||||
*
|
||||
* ⚠️ 旧实现在 `EdgeScanFor` 里按“未完成状态”逐个 Post:288 条信号时单帧 288 次,
|
||||
* 把消息队列和重绘打满,`WM_TIMER`(分组折起动画)因此被饿死(用户 2026-11-02 报告)。
|
||||
*/
|
||||
mutable std::uint64_t m_edgeScanRequestFrame = static_cast<std::uint64_t>(-1);
|
||||
/** 诊断计数:中心轴本地曲线计算失败次数(内存不足等)。0 = 一切正常。 */
|
||||
mutable std::size_t m_edgeScanLocalCurveFails = 0;
|
||||
|
||||
/**
|
||||
* @brief 累积状态上限(随可见信号总数缩放)。
|
||||
*
|
||||
* 每个信号最多两类状态(普通边沿计数 / 中心轴边沿计数),因此上限 ≥ `2 × 信号数`。
|
||||
* 固定上限(旧 64)在 288 条信号合并到同一网格时会让所有状态互相淘汰 ⇒
|
||||
* 面板永远停在“统计中…”(用户 2026-11-02 报告)。
|
||||
*/
|
||||
std::size_t EdgeScanStateLimit() const;
|
||||
|
||||
/**
|
||||
* @brief 边沿统计的统一实现(普通边沿计数与中心轴边沿计数共用)。
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user