Add docs/agent-handoff (backlog, execution state, verification, platform plan, per-task evidence), repo AGENTS.md, and architecture notes updated for the dual-renderer design.
5.6 KiB
P2-02 证据:右侧 Bash 面板滚动条与横纵交汇角
完成日期:2026-07-21(无人值守轮次)
结论:完成。右侧任务面板的代码框(#bl_code)与两栏 section 滚动区(#bl_scroll)滚动条统一为 8px、无箭头、handle 可见且 hover;横纵交汇角用 QPlainTextEdit::corner 子控件染成代码框背景 #fbfcfe,原生亮色 corner 方块消除。所有选择器均限定在 #bl_code/#bl_scroll,未添加任何无作用域的 QScrollBar/QAbstractScrollArea 规则。
交付物
| 文件 | 改动 |
|---|---|
ui/views/main_window.py |
主窗口全局 QSS 中 #bl_code 规则后插入一段完全限定作用域的滚动条 + corner 规则(QPlainTextEdit#bl_code QScrollBar:*、QPlainTextEdit#bl_code::corner、QScrollArea#bl_scroll QScrollBar:*、QScrollArea#bl_scroll::corner);#bl_code 原有背景/边框/圆角/文本样式一字未动 |
tests/diag_panel_scrollbar.py |
新建:离屏测量 + 断言 + 局部截图(面板全貌、代码框 render 图、角落 4x 放大) |
截图(docs/agent-handoff/evidence/):p2-02-panel.png、p2-02-outbox-render.png、p2-02-codebox-corner-4x.png。
关键设计决策
- 作用域 = objectName 限定,零全局规则。 主窗口全局 QSS 此前没有任何
QScrollBar规则(各弹窗/附件区各自setStyleSheet),右侧面板因此落到原生 Windows 滚动条(带箭头、17px、亮色 corner 方块)。新增规则全部写成QPlainTextEdit#bl_code …/QScrollArea#bl_scroll …形式,只可能匹配右面板内的对象名,结构上不可能泄漏到其他控件。 - corner 用
QAbstractScrollArea::corner子控件语法(QPlainTextEdit#bl_code::corner { background-color: #fbfcfe; })——Qt 文档支持的子控件,与代码框背景同色,即 backlog「corner 与代码框背景一致」;未使用不存在的QScrollBar::corner。section 滚动区::corner置透明(其横向滚动条恒关,corner 本不显示,属保险)。 - 口径与仓库既有风格一致:8px 厚、
add-line/sub-line置 0 隐藏箭头、#d0d0d0handle +#a0a0a0hover、圆角 4px——与modern_scrollbar_qss及附件预览区风格同源,只是作用域不同。
验证(全部显式 timeout)
| 套件 | 结果 | 预算 |
|---|---|---|
tests/diag_panel_scrollbar.py(新) |
18 项 ALL PASS EXIT=0 | 180s |
tests/smoke_bash_panel.py |
140 项 ALL PASS EXIT=0 | 240s |
回归 tests/smoke_offscreen.py |
ALL PASS 8/8 EXIT=0 | 240s |
回归 tests/run_tests.py |
41/41 EXIT=0 | 300s |
回归 smoke_timeline / smoke_midswitch / test_main_window_event_filter |
11/11、7/7、ALL PASS,均 EXIT=0 | 各 ≤300s |
诊断脚本断言要点(对应 backlog「完成证据」):
- 厚度:代码框横/纵滚动条实际几何 = 8px 且
sizeHint= 8px(S1/S1b/S2/S2b);section 竖滚动条实际 = 8px(S3); - 箭头 extent:
subControlRect(CC_ScrollBar, SC_ScrollBarSubLine)在样式代理下 = 0(S4 三项)——即箭头子控件零尺寸; - corner:代码框
render()图中,右下角 8×8 交汇块渲染出#fbfcfe(9 px)、无(255,255,255)亮白像素(S5c/S5d); - 无泄漏:未命名
QPlainTextEdit横滚动条仍为原生口径(14px,S6);附件预览滚动条保持自身 6pxsizeHint(S7); - 截图三张落盘 evidence 目录,含角落 4x 放大图。
Windows 真机截图(backlog「完成证据」第二条):已完成(2026-09-17,Windows 11 真桌面,非 offscreen):diag_panel_scrollbar.py 直接运行 → EXIT=0、ALL PASS;实测代码框 H=8px V=8px、section V=8px、corner #fbfcfe 9 像素(与 offscreen 测量一致);三张截图已用真机渲染覆盖:p2-02-panel.png、p2-02-outbox-render.png、p2-02-codebox-corner-4x.png(07:20 时间戳)。运行期间生产 app 以 WebView2 在前台,diag 实例经 instance-lock 守卫自动回落 QtWebEngine,未误杀对方 WebView2 进程(T0 守卫真机验证)。Linux 真机截图仍待对应环境。
测试中发现的问题与教训
- offscreen 下
widget.grab()对QPlainTextEdit的文档区不填充(黑图):out_box.grab()整块 (0,0,0),但panel.grab()正常。改用ob.render(painter)(渲染到透明 QPixmap)后:文本色#243043、边框#e6eaf2、handle#d0d0d0、corner#fbfcfe全部出现——样式子控件在 offscreen 下正常渲染,只有文档区背景填充缺失(离屏渲染怪癖,非产品 bug)。像素断言一律走render(),且必须先做健全性检查(文本色/handle 色像素计数 > 0)防黑图假通过。 - PyQt6 API 坑(三连):
Qt.Vertical/Qt.Horizontal短名已移除 →Qt.Orientation.*;QStyleOptionSlider(widget)构造器未绑定(只收无参/拷贝)→ 用QStyleOptionSlider();subControlRect参数序是(ComplexControl, QStyleOption, SubControl, widget),且滚动条箭头子控件在 PyQt6 枚举里叫SC_ScrollBarSubLine/SC_ScrollBarAddLine(不是 C++ 文档里的SC_DownArrowButton);CC_ScrollBar属于QStyle.ComplexControl而非ControlElement。- 裸控件(无样式表祖先)的
style()是基础风格且空 option 下subControlRect返回 0 矩形——「原生参照」只能靠sizeHint/实际几何(如原生横条 14px)对照,不能靠 subControlRect。
- 测试数据:
out_box要同时出横纵滚动条,必须「超宽单行(NoWrap 触发横条)+ 足够行数(触发纵条)」,只给长单行时纵条不可见。