6.Qt绘图系统的核心类有哪些?区别是什么?
Qt绘图系统提供了多个类用于2D图形绘制,主要分为基于QPainter的立即模式 和基于Graphics View的场景图模式两大体系。
1. 核心类概览
立即模式绘图(Immediate Mode)
- QPainter - 绘图引擎,执行实际绘制操作
- QPaintDevice - 绘图设备的抽象基类
- QPaintEngine - 底层绘图引擎接口
- QPen - 画笔(轮廓样式)
- QBrush - 画刷(填充样式)
- QPainterPath - 复杂路径定义
场景图模式(Scene Graph)
- QGraphicsView - 视图窗口
- QGraphicsScene - 场景容器
- QGraphicsItem - 图形项基类
- QGraphicsItemGroup - 图形项组
其他重要类
- QImage - 图像处理
- QPixmap - 像素图显示
- QPicture - 绘图命令记录
2. 主要类详解与区别
QPainter vs QGraphicsView
| 特性 | QPainter | QGraphicsView |
|---|---|---|
| 绘制模式 | 立即模式,立即执行绘制命令 | 保留模式,维护场景图 |
| 性能 | 简单绘制性能好 | 复杂场景管理性能好 |
| 内存使用 | 低 | 较高(维护场景数据) |
| 交互支持 | 需要手动处理 | 内置交互(选择、拖动等) |
| 适用场景 | 简单绘图、自定义控件、图像处理 | 复杂图形界面、CAD、图表、游戏 |
| 坐标系 | 物理坐标系 | 逻辑坐标系(支持变换) |
QPaintDevice 子类对比
| 类 | 用途 | 特点 |
|---|---|---|
| QWidget | 控件绘图 | 双缓冲,支持部分更新 |
| QPixmap | 屏幕显示 | 平台优化,适合显示操作 |
| QImage | 图像处理 | 独立于硬件,像素级访问 |
| QPicture | 记录回放 | 保存和重现绘制命令 |
QPixmap vs QImage
| 特性 | QPixmap | QImage |
|---|---|---|
| 存储位置 | 显存/GPU | 内存/CPU |
| 像素访问 | 慢(需要转换) | 快(直接访问) |
| 硬件加速 | 支持 | 不支持 |
| 平台依赖 | 是 | 否 |
| 文件格式 | 有限 | 丰富(BMP、PNG、JPEG等) |
| 适用场景 | 界面显示 | 图像处理、修改、保存 |
3. 使用示例对比
QPainter 立即模式示例
cpp
c++
// 在QWidget中绘制
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this); // 在widget上绘制
// 设置画笔和画刷
painter.setPen(QPen(Qt::blue, 2));
painter.setBrush(QBrush(Qt::yellow));
// 绘制图形
painter.drawRect(10, 10, 100, 50);
painter.drawEllipse(50, 50, 60, 60);
// 绘制文本
painter.drawText(20, 90, "QPainter示例");
}
QGraphicsView 场景图示例
cpp
c++
// 创建场景和视图
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView *view = new QGraphicsView(scene);
// 添加图形项
QGraphicsRectItem *rect = scene->addRect(10, 10, 100, 50);
rect->setBrush(Qt::yellow);
rect->setFlag(QGraphicsItem::ItemIsMovable); // 可拖动
QGraphicsEllipseItem *ellipse = scene->addEllipse(50, 50, 60, 60);
ellipse->setBrush(Qt::blue);
ellipse->setFlag(QGraphicsItem::ItemIsSelectable); // 可选择
// 添加文本
QGraphicsTextItem *text = scene->addText("Graphics View示例");
text->setPos(20, 90);
4. 绘图系统的层次结构
text
┌─────────────────────────────────────┐
│ 应用程序/自定义控件 │
├─────────────────────────────────────┤
│ QPainter(绘图引擎) │
├─────────────────────────────────────┤
│ QPaintDevice(绘图设备抽象) │
│ ├─ QWidget(控件) │
│ ├─ QPixmap(像素图) │
│ ├─ QImage(图像) │
│ └─ QPicture(绘图命令) │
├─────────────────────────────────────┤
│ QPaintEngine(平台相关实现) │
│ ├─ Raster(光栅) │
│ ├─ OpenGL(OpenGL) │
│ └─ OpenVG(矢量) │
└─────────────────────────────────────┘
5. 场景图(Graphics View)架构
text
┌─────────────────────────────────────┐
│ QGraphicsView(视图) │
│ 显示和管理场景 │
├─────────────────────────────────────┤
│ QGraphicsScene(场景) │
│ 管理所有图形项 │
├─────────────────────────────────────┤
│ QGraphicsItem(图形项) │
│ ├─ QGraphicsRectItem │
│ ├─ QGraphicsEllipseItem │
│ ├─ QGraphicsTextItem │
│ ├─ QGraphicsPixmapItem │
│ ├─ QGraphicsPathItem │
│ └─ 自定义QGraphicsItem │
└─────────────────────────────────────┘
6. 选择指南
使用 QPainter 的情况:
- 简单绘图需求
- 自定义控件绘制
- 图像处理操作
- 需要直接控制绘制过程
- 性能要求高且场景简单
使用 Graphics View 的情况:
- 大量图形项需要管理
- 需要交互(选择、拖动、缩放)
- 复杂场景变换
- 需要分层和分组
- 图形项需要独立逻辑
7. 高级特性对比
| 特性 | QPainter | Graphics View |
|---|---|---|
| 抗锯齿 | setRenderHint(QPainter::Antialiasing) |
setRenderHint(QPainter::Antialiasing) |
| 变换 | 支持(缩放、旋转、平移) | 支持(场景和视图级别) |
| 裁剪 | setClipRect(), setClipPath() |
视图裁剪,项级别裁剪 |
| 双缓冲 | 默认(在QWidget中) | 默认支持 |
| 动画 | 需手动实现 | 有QGraphicsItemAnimation支持 |
| 碰撞检测 | 需手动实现 | 内置碰撞检测 |
8. 性能优化建议
QPainter 优化:
cpp
C++
void paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); // 按需使用
// 只绘制需要更新的区域
QRect rectToUpdate = event->rect();
// 避免不必要的状态改变
painter.setPen(QPen(Qt::black, 1));
// 多次绘制...
}
Graphics View 优化:
cpp
c++
QGraphicsView *view = new QGraphicsView(scene);
view->setRenderHint(QPainter::Antialiasing); // 选择性使用
view->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); // 智能更新
view->setOptimizationFlag(QGraphicsView::DontSavePainterState); // 优化标志
总结
Qt绘图系统提供了两套互补的解决方案:
- QPainter:轻量、灵活,适合简单绘制和自定义控件
- Graphics View:功能完整,适合复杂交互式图形应用
在实际开发中,可以根据需求选择或组合使用这两种方式。例如,可以在自定义控件中使用QPainter进行绘制,而在需要管理大量交互式图形时使用Graphics View框架。