Instruction file imported from HATTER-LONG/Kangaroo (
.github/instructions/qt-qml.instructions.md). Copyright stays with the author.
OpenGeoLab Qt/QML Instructions
1. 分层原则
- QML 只负责界面编排、状态展示和用户意图转发,不承载核心业务逻辑。
- 复杂状态、长生命周期对象、协议拼装与错误处理优先放在 C++/Python 边界层中。
2. 组件组织
- 每个 qml 不要过长,要模块化拆分,每个页面应当由多个小组件组合而成,而不是一个大文件。
- 一个可复用组件优先一个
.qml文件,文件名使用 PascalCase。 id使用 lowerCamelCase,属性名保持语义明确,避免obj、tmp、data2之类的弱命名。- 页面级组件优先通过
ColumnLayout、RowLayout、GridLayout、SplitView组织,不要混用大量锚点和手工坐标导致响应式行为不可推导。 - 仅在确有必要时使用 JavaScript 片段;一旦逻辑开始涉及分支、状态机、数据整形或协议构造,应提取到后端桥接层。
- 避免在一个 QML 文件中同时承担页面容器、业务状态和复杂控件实现三种职责。
3. 数据流与交互
- 优先使用声明式绑定表达 UI 状态,不要用大量 imperative 赋值去“追状态”。
- 需要触发后端行为时,优先暴露少量明确的
Q_INVOKABLE方法或属性,而不是让 QML 依赖隐式副作用。 - 对同一份状态只保留一个真实来源;QML 中的镜像文本、选中项、预览图应从控制器属性推导,不要维护多份手动同步副本。
- 输入事件先转换为语义意图,再传给后端。例如 “框选 edge + face” 应传递选择框、过滤器、视口状态,而不是只传原始鼠标轨迹。
- 需要支持回放和 Python 导出时,QML 只负责采集交互上下文;真正的记录格式、脚本生成和回放计划必须在非 UI 层完成。
4. Qt/C++ 边界
- QML 与 C++ 的边界保持窄接口:少量
Q_PROPERTY、明确的Q_INVOKABLE、稳定的 JSON/值对象。 - 不要把大型可变对象图直接暴露给 QML;优先暴露只读属性、值语义快照或专用模型。
- 需要异步、长耗时或失败可见的操作时,要在边界层显式提供状态文本、进度或错误反馈,避免 QML 静默失败。
- 如果新增视口、选择、录制相关 UI,优先让 C++ 先产出“显式视图状态”和“语义选择命令”,再由 QML 展示结果。
- C++ 桥接代码仍需遵循仓库的 C++ instructions。
5. 视觉与可维护性
- 颜色、间距、圆角、字号等视觉常量优先集中管理,避免页面内散落硬编码。
- 文本说明、占位提示和状态展示要与实际协议能力一致,不要展示后端尚未支持的假功能。
- 对包含图片、快照、选择结果预览的界面,必须提供无结果时的空态文案。
- 控件文字优先简洁、可扫描;如果按钮触发的是协议示例,名称应直接反映动作,如
Snapshot、Box Select、Replay Export。
6. 性能与稳定性
- 避免在高频事件中创建大量临时 JavaScript 对象或触发深层绑定链。
- 对
Repeater、ListView、TableView等数据驱动控件,优先使用明确模型,不要通过手工拼接子项模拟列表。 - 注意绑定环和属性回写抖动;如果一个属性既由用户编辑又由后端回填,必须像当前
requestText一样显式处理同步边界。 - 不要在
Component.onCompleted中堆放大量初始化逻辑;可复用初始化应下沉到控制器或后端服务。
7. 生成代码时的默认行为
- 新增 QML 时默认提供合理的空态、错误态和只读展示态。
- 新增面向后端协议的按钮或菜单时,优先补齐对应的示例请求入口,而不是让用户手写复杂 JSON。
- 如果某个交互需要未来支持脚本导出或回放,默认预留“语义动作”命名,而不是以 UI 手势命名唯一入口。
- 遇到风格冲突时,以现有
src/app/resource/qml/Main.qml的组织方式和仓库通用指令为准。