Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← C++ 编程 / C++ Programming

Qt 与可视化 / Qt & Visualization

1. Qt 6 与科学可视化路线 / Qt 6 and Scientific Visualization Roadmap

2. 信号槽机制深度解析 / Qt Signals and Slots in Depth

3. 对象树与内存管理 / QObject Trees and Memory Management

4. CAE开发常用核心API实战 / Essential Qt APIs for CAE Development

5. Model/View架构与CAE数据处理 / Model-View Architecture and CAE Data Processing

6. 多线程与求解器集成 / Multithreading and Solver Integration

7. CAE软件架构实战模式 / Practical Architecture Patterns for CAE Software

8. 3D可视化与交互 / Interactive 3D Visualization

9. 实战案例:从零拆解一个FEA前后处理器 / Building an FEA Pre- and Post-Processor from Scratch

本页目录

Qt 6 与科学可视化路线 / Qt 6 and Scientific Visualization Roadmap ​

本区以 Qt 6 + CMake 为主线,既讲 Qt 机制,也明确它与标准 C++ 所有权、线程、ABI 和第三方渲染库的边界。

阅读路线 ​

  1. 信号槽与元对象
  2. QObject 对象树与生命周期
  3. QString、I/O、序列化与进程
  4. Model/View 正确性
  5. 线程与求解器集成
  6. CAE 文档/命令架构
  7. OpenGL、VTK 与交互
  8. FEA 前后处理器案例

Qt 在 CAE 中的角色与核心机制 是背景综述,适合在正式路线前快速浏览;主线从信号槽和元对象开始。

每篇主文章对应 topics/00—topics/08 的审校专题,集中记录版本、线程、ABI 和生产边界。

机制地图 ​

text
C++ objects / value data
       |
QObject + meta-object ---- signals/queued events ---- event loop/thread affinity
       |                                             |
parent-child ownership                          GUI thread
       |
Document/Command/Model ---- views/delegates ---- rendering context
       |                                             |
solver process/worker <---- cancellation ------ OpenGL/VTK resources
1
2
3
4
5
6
7
8
9

五条不变量 ​

  1. QObject parent 只表达特定所有权树,不是 GC;
  2. queued signal 需要接收线程事件循环,参数在排队期必须可复制/注册且语义安全;
  3. QWidget 及 GUI 资源只在 GUI 线程操作;
  4. Model 的 begin/end 通知必须精确包围底层数据变化;
  5. GPU/VTK/插件资源的销毁线程、context 和 ABI 必须与创建协议匹配。

Qt 6 边界 ​

  • 新项目优先 CMake target,如 Qt6::Core、Qt6::Widgets;
  • qmake 未从 Qt 6 完全移除,但不是新工程主线;
  • QString 仍以 UTF-16 code unit 语义存储,不是 UTF-8 string;
  • QTextCodec 位于兼容模块,新代码评估 QStringDecoder/Encoder/Converter;
  • 具体 API 取决于 Qt 6 小版本,文档和 CI 应固定最低版本;
  • Qt 插件的纯虚 C++ 接口不自动成为长期稳定 ABI。

自测 ​

  1. queued connection 为什么不等于线程安全?
  2. QObject 有 parent 时能否再由独立 unique_ptr 删除?
  3. OpenGL object 为什么不能在任意线程析构?

<details> <summary>参考答案</summary>

  1. 它只安排槽执行位置;共享数据、积压、取消和对象生命周期仍需协议。
  2. 不应有两个独立删除所有者,否则 parent 和 unique_ptr 可能双重删除。
  3. GPU 对象删除通常要求兼容且 current 的 context,context/线程生命周期需匹配。

</details>

Qt 的核心不是控件,而是事件驱动对象系统 ​

text
C++ object model
   + QObject meta-object (signals/slots/properties/type info)
   + object tree ownership
   + event loop and thread affinity
   + Model/View data contracts
   + platform/rendering backends
1
2
3
4
5
6

Qt 在 ISO C++ 之上增加 moc 生成的元数据与运行时连接系统。Q_OBJECT 不是 C++ 关键字,构建系统会调用 moc 生成额外 C++ 源码,再参与编译链接。

一次 GUI 事件怎样流动 ​

text
OS input/window message
 -> Qt platform plugin
 -> QApplication event loop
 -> QObject::event / widget event handler
 -> model/state changes
 -> signal emission
 -> direct call or queued event
 -> update request
 -> paint/render backend
1
2
3
4
5
6
7
8
9

GUI 线程不能长时间阻塞,否则输入、定时器、queued signal 和绘制都停止推进。耗时任务移到 worker,但 UI 对象仍通常只在 GUI 线程访问。

QObject 的两条正交关系 ​

text
ownership tree: parent ----owns----> child
thread affinity: QObject ---------> one QThread/event dispatcher
1
2

parent 析构会删除 children;这不等于 C++ shared ownership。对象只能被其亲和线程安全地处理 queued event/定时器,带 parent 的对象不能随意 moveToThread,因为父子必须同线程。

Signal/Slot 的连接类型 ​

text
sender thread == receiver thread + Auto -> Direct call
different threads + Auto -> Queued event to receiver thread
BlockingQueued -> sender waits receiver(误用可死锁)
1
2
3

queued connection 需要接收线程事件循环运行;参数需可复制/移动并在元类型系统可用。连接存在不代表接收者一定及时执行,关闭时还要处理已排队事件。

Model/View 为什么重于把数据塞进控件 ​

text
domain data/model
 -> QAbstractItemModel index/data/rowCount contracts
 -> proxy sort/filter
 -> view requests visible cells
 -> delegate paints/edits
1
2
3
4
5

模型不应返回指向短命临时数据的 index/internalPointer。插入删除必须 begin/end 成对,让 view 和 persistent index 更新;大模型只提供可见数据,不复制到 UI 控件。

数据与编码边界 ​

Qt 6 的 QString 表示 Unicode 文本,UTF-8 网络/文件边界显式用 toUtf8/fromUtf8;QByteArray 是字节,不自动是文本。序列化协议必须写版本、字节序、长度上限和错误处理,不能直接 dump C++/QObject 内存布局。

线程与取消的推荐结构 ​

text
GUI owner
 -> creates worker/controller
 -> request work via queued signal/task
worker checks stop token/flag and reports progress
shutdown: stop input -> request cancellation -> wait thread -> delete objects
1
2
3
4
5

QThread 对象本身通常活在创建它的线程;run() 才在工作线程。推荐 worker QObject moveToThread 或受控任务池,不要把 QThread 子类成员误认为自动属于工作线程。

渲染资源的线程与上下文所有权 ​

OpenGL/Vulkan/QRhi 等资源不仅有 C++ 对象生命,还绑定 device/context/thread 与 GPU in-flight 工作:

text
CPU wrapper lifetime
GPU resource lifetime
command submitted -------- GPU finishes
destroy only after correct context + no in-flight use
1
2
3
4

窗口关闭时先停止提交、等待/回收在途资源,再销毁渲染器和 surface。

CAE 应用分层 ​

text
Document/domain model
├── undo/redo commands
├── serialization/versioning
├── compute jobs + cancellation
├── Qt Model/View adapters
└── rendering scene/resources
1
2
3
4
5
6

不要让 widget 同时拥有业务数据、启动后台计算、解析文件和管理 GPU。Document 作为组合根明确修改状态、脏标记、保存快照与关闭协议。

学习路线 ​

text
Qt 版本/字符串/容器
 -> QObject/meta-object/signal-slot
 -> object tree + event loop + thread affinity
 -> Model/View
 -> data I/O/versioning
 -> worker cancellation/shutdown
 -> rendering resources
 -> plugin ABI + CAE architecture
1
2
3
4
5
6
7
8

综合面试与自测 ​

问:queued signal 什么时候执行? 答:事件被投递到 receiver 亲和线程,待其事件循环处理;发送返回不代表槽已运行。

问:deleteLater 为什么存在? 答:把 QObject 删除安排到其事件循环的安全时机,常用于跨回调/线程关闭;事件循环不再运行时需另有关闭协议。

  1. QThread 对象属于哪个线程? 答:默认属于创建它的线程,不是 run 执行线程。
  2. parent 能否替代 shared_ptr? 答:它表达树状析构所有权,不表达任意共享所有权。
  3. 模型修改为何要 begin/end? 答:通知 view/proxy/persistent index 正确更新内部状态。

工程深化:把本篇知识落到项目里 ​

这一节不是为了凑篇幅,而是把《Qt 6 与科学可视化路线 / Qt 6 and Scientific Visualization Roadmap》从“知道概念”推进到“能在项目里稳定使用”。 阅读时可以把每个知识点都追问成四件事:它保护什么边界,失败时有什么现象,怎样最小复现,怎样写进团队流程。

text
concept -> boundary -> failure signal -> minimal proof -> project rule
1

工程切片 1:最小可复现样例 ​

**场景。**围绕 渲染资源 建一个很小的案例,不要一开始就放进完整业务系统。把问题压缩到一个可以提交给同事的目录,保留源码、构建命令、版本输出和预期现象。

**边界。**先判断这里讨论的是 渲染资源、场景图 还是 数据上传 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 渲染资源 -> 场景图 -> 数据上传 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 2:接口边界 ​

**场景。**围绕 场景图 建一个很小的案例,不要一开始就放进完整业务系统。写清调用方能依赖什么、不能依赖什么,并把隐式假设转换成命名函数、配置项或测试。

**边界。**先判断这里讨论的是 场景图、数据上传 还是 相机交互 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 场景图 -> 数据上传 -> 相机交互 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 3:失败注入 ​

**场景。**围绕 数据上传 建一个很小的案例,不要一开始就放进完整业务系统。故意制造一个常见错误,让日志、断言或测试先失败,再用修复后的证据说明规则生效。

**边界。**先判断这里讨论的是 数据上传、相机交互 还是 帧预算 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 数据上传 -> 相机交互 -> 帧预算 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 4:跨平台差异 ​

**场景。**围绕 相机交互 建一个很小的案例,不要一开始就放进完整业务系统。至少比较 Windows、Linux 或不同编译器下的一个差异,记录差异属于标准、实现还是平台约定。

**边界。**先判断这里讨论的是 相机交互、帧预算 还是 资源释放 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 相机交互 -> 帧预算 -> 资源释放 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 5:性能观察 ​

**场景。**围绕 帧预算 建一个很小的案例,不要一开始就放进完整业务系统。用小规模和压力规模各跑一次,区分算法成本、同步成本、I/O 成本和工具链配置成本。

**边界。**先判断这里讨论的是 帧预算、资源释放 还是 渲染资源 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 帧预算 -> 资源释放 -> 渲染资源 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 6:生命周期 ​

**场景。**围绕 资源释放 建一个很小的案例,不要一开始就放进完整业务系统。标出资源创建、转移、共享、停止和销毁的顺序,特别关注错误返回和提前退出路径。

**边界。**先判断这里讨论的是 资源释放、渲染资源 还是 场景图 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源释放 -> 渲染资源 -> 场景图 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 7:诊断证据 ​

**场景。**围绕 渲染资源 建一个很小的案例,不要一开始就放进完整业务系统。保留命令、日志、符号、栈、测试输出或截图,让结论可以被另一个环境重新验证。

**边界。**先判断这里讨论的是 渲染资源、场景图 还是 数据上传 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 渲染资源 -> 场景图 -> 数据上传 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 8:维护策略 ​

**场景。**围绕 场景图 建一个很小的案例,不要一开始就放进完整业务系统。把一次性经验沉淀到 README、CI、脚本、示例工程或检查表里,避免只存在个人记忆中。

**边界。**先判断这里讨论的是 场景图、数据上传 还是 相机交互 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 场景图 -> 数据上传 -> 相机交互 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 9:版本演进 ​

**场景。**围绕 数据上传 建一个很小的案例,不要一开始就放进完整业务系统。为未来变更预留兼容策略:版本号、特性位、弃用窗口、迁移脚本和回滚入口。

**边界。**先判断这里讨论的是 数据上传、相机交互 还是 帧预算 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 数据上传 -> 相机交互 -> 帧预算 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 10:最小消费者 ​

**场景。**围绕 相机交互 建一个很小的案例,不要一开始就放进完整业务系统。从使用者角度写一个小程序或小工程,只依赖公开接口,验证安装包、头文件和运行时行为。

**边界。**先判断这里讨论的是 相机交互、帧预算 还是 资源释放 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 相机交互 -> 帧预算 -> 资源释放 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 11:边界复盘 ​

**场景。**围绕 帧预算 建一个很小的案例,不要一开始就放进完整业务系统。用一张表说明问题发生在源码、编译、链接、加载、运行、关闭或发布中的哪一层。

**边界。**先判断这里讨论的是 帧预算、资源释放 还是 渲染资源 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 帧预算 -> 资源释放 -> 渲染资源 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 12:反例训练 ​

**场景。**围绕 资源释放 建一个很小的案例,不要一开始就放进完整业务系统。写出一个看似能工作但不可维护的方案,再说明它在规模、团队协作或发布时会怎样失败。

**边界。**先判断这里讨论的是 资源释放、渲染资源 还是 场景图 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源释放 -> 渲染资源 -> 场景图 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 13:最小可复现样例 ​

**场景。**围绕 渲染资源 建一个很小的案例,不要一开始就放进完整业务系统。把问题压缩到一个可以提交给同事的目录,保留源码、构建命令、版本输出和预期现象。

**边界。**先判断这里讨论的是 渲染资源、场景图 还是 数据上传 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 渲染资源 -> 场景图 -> 数据上传 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 14:接口边界 ​

**场景。**围绕 场景图 建一个很小的案例,不要一开始就放进完整业务系统。写清调用方能依赖什么、不能依赖什么,并把隐式假设转换成命名函数、配置项或测试。

**边界。**先判断这里讨论的是 场景图、数据上传 还是 相机交互 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 场景图 -> 数据上传 -> 相机交互 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 15:失败注入 ​

**场景。**围绕 数据上传 建一个很小的案例,不要一开始就放进完整业务系统。故意制造一个常见错误,让日志、断言或测试先失败,再用修复后的证据说明规则生效。

**边界。**先判断这里讨论的是 数据上传、相机交互 还是 帧预算 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 数据上传 -> 相机交互 -> 帧预算 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 16:跨平台差异 ​

**场景。**围绕 相机交互 建一个很小的案例,不要一开始就放进完整业务系统。至少比较 Windows、Linux 或不同编译器下的一个差异,记录差异属于标准、实现还是平台约定。

**边界。**先判断这里讨论的是 相机交互、帧预算 还是 资源释放 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 相机交互 -> 帧预算 -> 资源释放 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 17:性能观察 ​

**场景。**围绕 帧预算 建一个很小的案例,不要一开始就放进完整业务系统。用小规模和压力规模各跑一次,区分算法成本、同步成本、I/O 成本和工具链配置成本。

**边界。**先判断这里讨论的是 帧预算、资源释放 还是 渲染资源 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 帧预算 -> 资源释放 -> 渲染资源 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 18:生命周期 ​

**场景。**围绕 资源释放 建一个很小的案例,不要一开始就放进完整业务系统。标出资源创建、转移、共享、停止和销毁的顺序,特别关注错误返回和提前退出路径。

**边界。**先判断这里讨论的是 资源释放、渲染资源 还是 场景图 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 资源释放 -> 渲染资源 -> 场景图 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 19:诊断证据 ​

**场景。**围绕 渲染资源 建一个很小的案例,不要一开始就放进完整业务系统。保留命令、日志、符号、栈、测试输出或截图,让结论可以被另一个环境重新验证。

**边界。**先判断这里讨论的是 渲染资源、场景图 还是 数据上传 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 渲染资源 -> 场景图 -> 数据上传 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 20:维护策略 ​

**场景。**围绕 场景图 建一个很小的案例,不要一开始就放进完整业务系统。把一次性经验沉淀到 README、CI、脚本、示例工程或检查表里,避免只存在个人记忆中。

**边界。**先判断这里讨论的是 场景图、数据上传 还是 相机交互 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 场景图 -> 数据上传 -> 相机交互 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

工程切片 21:版本演进 ​

**场景。**围绕 数据上传 建一个很小的案例,不要一开始就放进完整业务系统。为未来变更预留兼容策略:版本号、特性位、弃用窗口、迁移脚本和回滚入口。

**边界。**先判断这里讨论的是 数据上传、相机交互 还是 帧预算 的责任;如果三者混在一起,先把输入、输出和所有权拆开。

text
input -> 数据上传 -> 相机交互 -> 帧预算 -> observable result
1

**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。

**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。

**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?

本篇收束 ​

掌握《Qt 6 与科学可视化路线 / Qt 6 and Scientific Visualization Roadmap》的标志,不是记住所有名词,而是能把 渲染资源、场景图、数据上传、相机交互、帧预算、资源释放 放进一条可验证的工程链路。 先用最小样例建立判断,再用测试和脚本固定判断,最后把失败证据留给未来的自己和团队。

最后更新于:

Pager
上一篇← C++ 编程 / C++ Programming
下一篇2. 信号槽机制深度解析 / Qt Signals and Slots in Depth

持续记录,持续成长

Copyright © Tidenflow