qt-C++笔记之创建和初始化 QGraphicsScene
和 QGraphicsView
并关联视图和场景的方法
code review!
参考笔记
1.qt-C++笔记之创建和初始化 QGraphicsScene
和 QGraphicsView
并关联视图和场景的方法
2.qt-C++笔记之QGraphicsScene和 QGraphicsView中setScene、通过scene得到view、通过view得scene
文章目录
- qt-C++笔记之创建和初始化 `QGraphicsScene` 和 `QGraphicsView` 并关联视图和场景的方法
- 1. 栈分配 `QGraphicsScene` 和 `QGraphicsView`
- 2. 堆分配 `QGraphicsScene` 和 `QGraphicsView`
- 3. 堆分配 `QGraphicsScene`,栈分配 `QGraphicsView`
- 4. 堆分配并利用父子关系管理
- 5. 使用 Qt Designer 通过 UI 文件创建(推荐方式之一)
- 总结比较
- 推荐使用方式
在使用 Qt 开发图形界面应用程序时,
QGraphicsScene
和
QGraphicsView
是处理和显示图形项的核心类。正确地创建和初始化这两个类对于应用程序的性能和内存管理至关重要。本节将详细介绍创建和初始化
QGraphicsScene
和
QGraphicsView
的常见方式,分析它们之间的关系,并讨论不同内存分配方式的优缺点及适用场景。
1. 栈分配 QGraphicsScene
和 QGraphicsView
QGraphicsScene scene;
QGraphicsView view(&scene);
特点
- 栈上分配:
scene
和view
都是在栈上分配的对象。 - 作用域管理:它们的生命周期由所在的作用域控制,离开作用域时会自动销毁。
- 关联方式:
view
在构造函数中接受scene
的地址,直接关联二者。
优点
- 自动内存管理:不需要手动释放内存,避免了内存泄漏的风险。
- 简单易用:代码简洁明了,适合快速开发。
缺点
- 栈内存有限:栈内存空间较小,如果场景中包含大量图形项,可能导致栈溢出。
- 生命周期受限:无法在作用域之外使用
scene
或view
,限制了它们的可用范围。
适用场景
- 短生命周期的应用:如小型工具或临时演示程序。
- 简单场景:不需要大量图形项或复杂交互的情况。
2. 堆分配 QGraphicsScene
和 QGraphicsView
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView *view = new QGraphicsView(scene);
特点
- 堆上分配:
scene
和view
都是在堆上动态分配的对象。 - 手动内存管理:需要开发者在合适的时机手动释放内存(通常使用
delete
)。 - 关联方式:
view
通过构造函数接受scene
的指针,建立关联。
优点
- 灵活性高:可以动态管理对象的生命周期,适应复杂的应用需求。
- 长期存在:适合需要在整个程序生命周期中存在的场景和视图。
缺点
- 内存管理复杂:需要手动释放内存,容易出现内存泄漏或悬空指针。
- 错误风险高:释放顺序不当可能导致未定义行为,需要仔细管理。
适用场景
- 复杂应用程序:需要动态创建和销毁大量场景和视图的程序。
- 资源管控:需要精细控制内存和资源的分配与释放。
3. 堆分配 QGraphicsScene
,栈分配 QGraphicsView
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView view(scene);
特点
- 混合分配:
scene
在堆上动态分配,view
在栈上分配。 - 部分手动管理:
scene
需要手动释放内存,view
由作用域自动管理。
优点
- 视图自动管理:
view
不需要手动释放,减少了内存管理的负担。 - 长寿命场景:适合场景需要长期存在,但视图是临时的情况。
缺点
- 场景内存管理:
scene
的内存需要手动释放,可能导致内存泄漏。 - 关联风险:在
view
销毁后继续使用scene
时,需确保其合法性。
适用场景
- 临时视图:需要在不同地方显示同一场景的短期视图。
- 共享场景:多个视图共享一个长期存在的场景。
4. 堆分配并利用父子关系管理
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView *view = new QGraphicsView(scene);
view->setScene(scene); // 可选,如果构造函数已设置,可省略
特点
- 堆上分配:
scene
和view
都在堆上动态分配。 - 父子关系管理:通过 Qt 的对象树机制,
view
作为父对象,scene
作为子对象。 - 自动内存管理:当父对象销毁时,子对象会自动销毁。
优点
- 减少内存泄漏:利用父子关系,自动管理内存,降低内存泄漏风险。
- 结构清晰:对象间的关系明确,便于维护。
缺点
- 依赖父子关系:需要确保正确设置父子关系,否则内存管理仍需手动处理。
- 复杂性增加:在复杂应用中,需要仔细设计对象间的关系。
适用场景
- 长期存在的复杂应用:需要稳定且生命周期较长的场景和视图。
- 多层次对象管理:适用于对象间存在明显的层次关系的程序。
5. 使用 Qt Designer 通过 UI 文件创建(推荐方式之一)
在 Qt Designer 中,可以直接设计和布局 QGraphicsView
,然后在代码中动态创建并关联 QGraphicsScene
。
步骤
- 在 Qt Designer 中设计界面:
- 拖放一个
QGraphicsView
到 UI 界面中。
- 拖放一个
- 在代码中设置场景:
QGraphicsScene *scene = new QGraphicsScene(this); // this 通常是指主窗口
ui->graphicsView->setScene(scene);
特点
- 可视化设计:利用 Qt Designer 直观地设计界面布局。
- 父子关系管理:
scene
的父对象设置为主窗口,自动管理内存。
优点
- 代码简洁:界面布局和代码逻辑分离,代码更清晰。
- 自动内存管理:借助父子关系,减少内存泄漏的风险。
缺点
- 学习成本:需要熟悉 Qt Designer 和 UI 文件的使用方法。
- 灵活性:某些动态布局可能不如手写代码灵活。
适用场景
- UI 集中管理的项目:界面复杂且需要频繁调整的应用程序。
- 团队协作:设计人员和开发人员分工合作的项目。
总结比较
方式 | 场景分配 | 视图分配 | 内存管理 | 适用场景 |
---|---|---|---|---|
1. 栈分配场景和视图 | 栈 | 栈 | 自动管理 | 简单、短生命周期的场景 |
2. 堆分配场景和视图 | 堆 | 堆 | 手动管理 | 长期存在、复杂的场景 |
3. 堆分配场景 + 栈分配视图 | 堆 | 栈 | 部分手动管理 | 临时视图,长期存在的场景 |
4. 堆分配并利用父子关系管理 | 堆 | 堆 | 父子关系自动管理 | 复杂项目,长期存在的视图和场景 |
5. 使用 Qt Designer 通过 UI 文件创建 | 可选(堆) | 可选(堆) | 父子关系自动管理 | 使用 Qt Designer 的项目 |
推荐使用方式
- 简单程序:如果是简单的、短期的程序,建议使用 方式 1,即栈上分配,自动管理内存,代码简洁。
- 复杂程序:对于大型或复杂的应用程序,推荐使用 方式 4 或 方式 5,结合父子关系和 Qt Designer,既有利于内存管理,又能提高开发效率。
- 需要动态管理生命周期:如果需要在运行时动态创建和销毁场景或视图,可以考虑 方式 2 或 方式 3,但要注意正确管理内存,防止泄漏。
通过对以上五种方式的分析,可以根据具体的应用需求和项目规模,选择最适合的创建和初始化 QGraphicsScene
和 QGraphicsView
的方法。这不仅有助于提高程序的性能和稳定性,还能降低内存泄漏和其他潜在问题的风险。
在实际开发中,遵循良好的内存管理原则,充分利用 Qt 的父子对象机制,以及借助工具(如 Qt Designer)进行界面设计,都能提高开发效率和代码质量。