Qt高级绘图:从QPainter到图形视图框架
Qt高级绘图:从QPainter到图形视图框架
1.Qt高级绘图:从QPainter到图形视图框架
在 Qt C++ 中,高级绘图功能主要由 Qt Graphics View Framework(图形视图框架)和 Qt Paint System(绘图系统)共同支撑。它们提供了从底层像素绘制到高层场景管理的一整套机制。
下面分别介绍这两个体系中的核心类及其关系:
一、Qt Paint System(基础绘图系统)
用于直接在窗口、控件或图像上进行 2D 绘图。
核心类
| 类名 | 作用 |
|---|---|
QPainter |
执行实际绘图操作的类,提供 drawLine、drawRect、drawText 等方法 |
QPaintDevice |
抽象基类,表示可以被 QPainter 绘制的目标设备 |
QWidget |
继承自 QPaintDevice,是最常用的绘图目标(重写 paintEvent) |
QPixmap / QImage / QPicture |
都继承自 QPaintDevice,分别用于屏幕优化位图、可直接访问像素的图像、可记录/回放的绘图指令 |
类关系简图
QPaintDevice
↑
├── QWidget
├── QPixmap
├── QImage
└── QPicture
QPainter ——(uses)——→ QPaintDevice
注意:
QPainter必须在QPaintDevice的paintEvent()(对 QWidget)或显式 begin/end 范围内使用。
二、Qt Graphics View Framework(高级图形视图框架)
适用于需要管理大量 2D 图形项、支持缩放/平移/交互的复杂场景(如流程图、CAD、游戏地图等)。
三大核心组件(MVC 架构思想)
| 组件 | 类 | 作用 |
|---|---|---|
| Model(数据) | QGraphicsScene |
存储和管理所有图形项(QGraphicsItem 及其子类) |
| View(视图) | QGraphicsView |
提供可视化窗口,支持滚动、缩放、拖拽等交互 |
| Item(元素) | QGraphicsItem |
场景中的基本图形单元(如矩形、文本、自定义图形) |
核心类详解
1. QGraphicsItem(抽象基类)
- 所有图形项的基类。
- 子类包括:
QGraphicsRectItemQGraphicsEllipseItemQGraphicsTextItemQGraphicsPixmapItemQGraphicsPathItemQGraphicsLineItemQGraphicsPolygonItem- 以及可自定义的派生类(需重写
paint()和boundingRect())
2. QGraphicsScene
- 管理大量
QGraphicsItem。 - 支持碰撞检测、选中、焦点、事件传播等。
- 不直接显示,需通过
QGraphicsView显示。
3. QGraphicsView
- 继承自
QScrollArea,提供滚动区域。 - 可设置变换(如缩放
scale()、旋转rotate())。 - 可自定义渲染(如抗锯齿、OpenGL 后端)。
类关系简图
QGraphicsItem ←─── QGraphicsRectItem, QGraphicsTextItem, ...
↑
│ (owned by)
QGraphicsScene ←───(displayed in)─── QGraphicsView
↑
│ (inherits)
QObject
注意:
QGraphicsView本身是一个 widget,内部使用QPainter渲染QGraphicsScene的内容。
三、其他高级绘图相关类
| 类 | 说明 |
|---|---|
QTransform |
表示 2D 仿射变换(平移、旋转、缩放、剪切) |
QPen / QBrush |
控制线条样式和填充样式,用于 QPainter 或 QGraphicsItem |
QPainterPath |
描述复杂路径,可用于裁剪、填充或作为 QGraphicsPathItem |
QStyleOptionGraphicsItem |
在自定义 QGraphicsItem::paint() 时传递样式信息 |
四、典型使用流程对比
基础绘图(QWidget + QPainter)
void MyWidget::paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.drawRect(10, 10, 100, 50);
}
高级绘图(Graphics View)
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsView *view = new QGraphicsView(scene);
QGraphicsRectItem *rect = scene->addRect(10, 10, 100, 50);
rect->setFlag(QGraphicsItem::ItemIsMovable); // 可拖动
view->show();
总结
| 特性 | Paint System | Graphics View Framework |
|---|---|---|
| 适用场景 | 简单、静态绘图(如自定义控件) | 复杂、动态、交互式图形(如编辑器、游戏) |
| 性能 | 轻量,但管理大量对象效率低 | 高效(使用 BSP 树优化渲染与查找) |
| 交互 | 需手动处理事件 | 内置选中、拖拽、碰撞检测 |
| 缩放/平移 | 需手动实现 | 内置支持(QGraphicsView::scale()) |
如果你有具体应用场景(比如做矢量绘图软件、流程图编辑器、2D 游戏等),我可以进一步推荐合适的类组合和设计模式。
一、Qt Paint System(基础绘图系统)
2.QPainter
QPainter 是 Qt 框架中用于 2D 图形绘制的核心类,广泛用于自定义控件、图表、图像处理等场景。它提供了一套高级 API,可以在各种设备(如窗口、图像、打印机等)上进行绘图操作。
下面是对 QPainter 的详细讲解(基于 C++ 和 Qt6/Qt5):
一、基本概念
1. 绘图设备(Paint Device)
QPainter 可以在以下设备上绘图:
QWidget(窗口部件)QImage(内存中的图像)QPixmap(屏幕优化的图像)QPicture(记录绘图命令)QOpenGLWidget(通过 OpenGL 上下文)
2. 绘图坐标系统
- 默认原点
(0, 0)在左上角。 - X 轴向右为正,Y 轴向下为正。
- 所有绘图单位默认为像素(pixel)。
二、基本使用流程
void MyWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this); // this 是 QWidget 子类
painter.setPen(Qt::red);
painter.setBrush(Qt::blue);
painter.drawRect(10, 10, 100, 50);
}
注意:通常只在
paintEvent()中创建QPainter对象来绘制 widget。若要在其他地方绘图(如保存图像),可对QImage或QPixmap创建QPainter。
三、常用功能详解
1. 设置画笔(Pen)
控制线条颜色、宽度、样式等。
QPen pen;
pen.setColor(Qt::black);
pen.setWidth(2);
pen.setStyle(Qt::DashLine);
painter.setPen(pen);
// 或简写:
painter.setPen(QPen(Qt::red, 3, Qt::SolidLine));
2. 设置画刷(Brush)
控制填充区域的颜色和图案。
QBrush brush(Qt::yellow, Qt::BDiagPattern);
painter.setBrush(brush);
// 或
painter.setBrush(QColor(255, 0, 0, 128)); // 带透明度
3. 基本图形绘制
| 方法 | 功能 |
|---|---|
drawLine(x1,y1,x2,y2) |
画线 |
drawRect(x,y,w,h) |
画矩形(含填充) |
drawEllipse(x,y,w,h) |
画椭圆 |
drawText(x,y,"text") |
画文本 |
drawPixmap(x,y,pixmap) |
画图片 |
drawPath(QPainterPath) |
画复杂路径 |
示例:
painter.drawText(20, 20, "Hello QPainter!");
painter.drawEllipse(QPoint(100, 100), 30, 20);
4. 坐标变换(Transformations)
支持平移、旋转、缩放、仿射变换:
painter.translate(100, 100); // 平移原点
painter.rotate(45); // 顺时针旋转 45°
painter.scale(1.5, 1.5); // 缩放
painter.shear(0.2, 0); // 剪切
// 或使用 QTransform
QTransform transform;
transform.rotate(30);
painter.setTransform(transform);
注意:变换是累积的。可使用
save()/restore()保存和恢复状态。
5. 状态管理:save() 与 restore()
painter.save();
painter.setPen(Qt::red);
painter.translate(50, 50);
painter.drawRect(0, 0, 30, 30);
painter.restore(); // 恢复之前的 pen、transform 等
6. 抗锯齿(Anti-aliasing)
使图形边缘更平滑:
painter.setRenderHint(QPainter::Antialiasing, true);
常用 RenderHint:
QPainter::AntialiasingQPainter::SmoothPixmapTransformQPainter::TextAntialiasing
四、完整示例:自定义 Widget 绘图
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 画一个带边框的圆
painter.setPen(QPen(Qt::black, 2));
painter.setBrush(Qt::cyan);
painter.drawEllipse(50, 50, 100, 100);
// 画文字
QFont font = painter.font();
font.setPointSize(14);
painter.setFont(font);
painter.drawText(60, 170, "Custom Drawing");
}
};
五、离屏绘图(Off-screen Painting)
将内容绘制到 QImage 或 QPixmap,可用于保存图像或预渲染:
QImage image(200, 200, QImage::Format_ARGB32);
image.fill(Qt::white);
QPainter painter(&image);
painter.setPen(Qt::red);
painter.drawLine(0, 0, 200, 200);
painter.end();
image.save("output.png");
六、性能建议
- 避免在
paintEvent中做耗时操作(如文件读取、复杂计算)。 - 使用
QPixmap缓存静态内容(双缓冲技术)。 - 尽量减少
QPainter对象的创建次数。 - 利用
QRegion和clipPath限制重绘区域。
七、常见问题
Q: 为什么不在构造函数里用 QPainter?
A: 因为 widget 尚未完全初始化,且没有有效的绘制设备上下文。必须在 paintEvent() 或对 QImage/QPixmap 操作时使用。
Q: 如何强制重绘?
A: 调用 widget->update()(异步,高效)或 widget->repaint()(同步,慎用)。
八、参考文档
- Qt 官方文档 - QPainter
- 相关类:
QPen,QBrush,QFont,QTransform,QPaintDevice,QPaintEngine
如果你有具体应用场景(如画曲线、图表、动画、打印等),可以进一步说明,我可以给出针对性示例。
3.QGraphicsScene
QGraphicsScene 是 Qt 框架中用于管理 2D 图形项(QGraphicsItem)的场景类,是 Qt Graphics View Framework 的核心组成部分之一。它与 QGraphicsView(视图)和 QGraphicsItem(图形项)共同构成一个强大的 2D 图形渲染与交互系统。
一、基本概念
- QGraphicsScene:表示一个场景,用于容纳和管理大量的 2D 图形项(如矩形、椭圆、文本、自定义图形等)。
- QGraphicsView:是一个可滚动的视口(viewport),用于显示
QGraphicsScene的一部分。 - QGraphicsItem:代表场景中的单个图形元素,可以是 Qt 提供的标准项(如
QGraphicsRectItem、QGraphicsEllipseItem),也可以是自定义子类。
三者关系:
QGraphicsView → 显示 → QGraphicsScene → 管理 → 多个 QGraphicsItem
二、主要功能
1. 图形项管理
- 添加/删除图形项(
addItem(),removeItem()) - 查找图形项(
items(),itemAt()) - 分组(通过
QGraphicsItemGroup)
2. 坐标系统
- 场景使用浮点坐标(
qreal),支持高精度定位。 - 每个
QGraphicsItem有自己的局部坐标系,可通过mapToScene()/mapFromScene()转换。
3. 事件处理
- 支持鼠标、键盘、拖拽等事件的分发。
- 事件首先由
QGraphicsView接收,然后转发给场景,再由场景分发给合适的QGraphicsItem。
4. 渲染与性能优化
- 使用 BSP 树(Binary Space Partitioning)加速图形项查找和渲染。
- 支持裁剪(只渲染可见区域)、缓存等机制提升性能。
5. 选择与焦点
- 支持多选(
setSelectionArea())、键盘焦点项(setFocusItem())。 - 可设置选择模式(
setSelectionMode())。
三、常用 API(C++)
创建场景
QGraphicsScene *scene = new QGraphicsScene(this);
scene->setSceneRect(0, 0, 800, 600); // 设置场景范围
添加图形项
QGraphicsRectItem *rect = scene->addRect(100, 100, 200, 100, QPen(Qt::black), QBrush(Qt::blue));
QGraphicsEllipseItem *ellipse = scene->addEllipse(300, 200, 100, 100, QPen(Qt::red), QBrush(Qt::yellow));
QGraphicsTextItem *text = scene->addText("Hello QGraphicsScene!");
text->setPos(50, 50);
自定义图形项(继承 QGraphicsItem)
class MyItem : public QGraphicsItem {
public:
QRectF boundingRect() const override {
return QRectF(-10, -10, 20, 20);
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override {
painter->drawEllipse(boundingRect());
}
};
// 使用
MyItem *myItem = new MyItem();
scene->addItem(myItem);
myItem->setPos(400, 300);
事件处理(在自定义项中)
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
qDebug() << "Item clicked at:" << event->pos();
QGraphicsItem::mousePressEvent(event);
}
连接视图
QGraphicsView *view = new QGraphicsView(scene, this);
view->setRenderHint(QPainter::Antialiasing); // 抗锯齿
view->show();
选择与交互
scene->setSelectionArea(QPainterPath()); // 清除选择
scene->setSelectionMode(QGraphicsScene::MultiSelection); // 多选模式
坐标转换示例
// 将视图坐标转为场景坐标
QPoint viewPos = view->mapFromGlobal(QCursor::pos());
QPointF scenePos = view->mapToScene(viewPos);
// 获取该位置的图形项
QGraphicsItem *item = scene->itemAt(scenePos, view->transform());
四、高级特性
1. 动画支持
配合 QPropertyAnimation 或 QGraphicsItemAnimation(旧版)实现动画。
2. 拖放(Drag & Drop)
重写 dragEnterEvent、dropEvent 等方法支持拖放操作。
3. 层次结构(父子关系)
childItem->setParentItem(parentItem); // 建立父子关系
子项坐标相对于父项,变换会级联。
4. 碰撞检测
通过 collidingItems() 检测与其他项的碰撞(基于 shape() 或 boundingRect())。
五、性能建议
- 避免频繁调用
update(),尽量批量操作。 - 对静态内容使用
setCacheMode(QGraphicsItem::DeviceCoordinateCache)。 - 使用
setItemIndexMethod(QGraphicsScene::BspTreeIndex)(默认)加速查找。 - 大量项时考虑分页或 LOD(Level of Detail)策略。
六、完整最小示例(C++)
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
scene.setSceneRect(0, 0, 400, 300);
QGraphicsRectItem *rect = scene.addRect(50, 50, 100, 80, QPen(Qt::black), QBrush(Qt::green));
rect->setFlag(QGraphicsItem::ItemIsMovable); // 可移动
rect->setFlag(QGraphicsItem::ItemIsSelectable); // 可选择
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.setWindowTitle("QGraphicsScene Example");
view.resize(500, 400);
view.show();
return app.exec();
}
七、常见问题
| 问题 | 解决方案 |
|---|---|
| 图形项不显示 | 检查是否调用了 addItem(),场景矩形是否包含该项 |
| 无法交互 | 确保设置了 ItemIsMovable、ItemIsSelectable 等标志 |
| 坐标混乱 | 理解局部坐标 vs 场景坐标,善用 mapToScene() |
| 性能差 | 启用缓存、减少重绘、使用 BSP 索引 |
八、参考文档
- Qt 官方文档 - QGraphicsScene
- 《C++ GUI Programming with Qt 6》第 12 章(Graphics View)
如需进一步了解自定义图形项、动画、拖拽、缩放/平移控制等内容,可继续提问!
4.QGraphicsView
QGraphicsView 是 Qt 框架中用于显示和交互 QGraphicsScene 中图形项(QGraphicsItem)的视图组件。它是 Qt Graphics View Framework 的三大核心类之一,另外两个是:
QGraphicsScene:场景容器,管理大量 2D 图形项。QGraphicsItem:所有图形项的基类(如矩形、椭圆、自定义图形等)。
一、基本概念
1. 架构关系
QGraphicsItem(s) → QGraphicsScene → QGraphicsView
- QGraphicsItem:表示一个可绘制的对象(如点、线、图片、文本等),可以响应鼠标、键盘事件。
- QGraphicsScene:作为“画布”,容纳并管理多个
QGraphicsItem,负责碰撞检测、选中、渲染等逻辑。 - QGraphicsView:作为“窗口”或“视口”,提供滚动、缩放、平移等功能,将
QGraphicsScene的内容可视化。
二、基本使用示例(C++)
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 创建场景
QGraphicsScene scene;
scene.setSceneRect(0, 0, 800, 600);
// 添加一个矩形项
QGraphicsRectItem *rect = scene.addRect(100, 100, 200, 150);
rect->setBrush(Qt::red);
// 创建视图并设置场景
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing); // 抗锯齿
view.setWindowTitle("QGraphicsView 示例");
view.resize(800, 600);
view.show();
return app.exec();
}
三、QGraphicsView 核心功能详解
1. 视图变换(缩放、平移)
// 缩放
view.scale(1.2, 1.2); // 放大 20%
view.resetTransform(); // 重置变换
// 平移(通过设置视口中心)
view.centerOn(400, 300); // 将 (400,300) 居中显示
// 或者使用 scrollContentsBy / translate
更灵活的方式:重写
wheelEvent实现鼠标滚轮缩放:
void MyGraphicsView::wheelEvent(QWheelEvent *event)
{
double scaleFactor = 1.15;
if (event->angleDelta().y() > 0) {
scale(scaleFactor, scaleFactor);
} else {
scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}
}
2. 渲染优化
view.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿
view.setRenderHint(QPainter::SmoothPixmapTransform, true); // 平滑缩放图片
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); // 更新模式
常用更新模式:
MinimalViewportUpdate(默认):只重绘变化区域。FullViewportUpdate:整个视口重绘(适合复杂动画或透明效果)。
3. 交互控制
view.setDragMode(QGraphicsView::ScrollHandDrag); // 拖拽平移(像手抓着移动)
view.setDragMode(QGraphicsView::RubberBandDrag); // 橡皮筋选择多个项
4. 坐标系统
- 场景坐标(Scene Coordinates):以
QGraphicsScene为基准(通常原点在左上角)。 - 视图坐标(View Coordinates):以
QGraphicsView窗口为基准(像素坐标)。 - 项坐标(Item Coordinates):每个
QGraphicsItem自身的局部坐标。
常用转换函数:
QPointF scenePos = view.mapToScene(viewPos); // 视图 → 场景
QPoint viewPos = view.mapFromScene(scenePos); // 场景 → 视图
5. 背景与网格(自定义绘制)
重写 drawBackground():
class MyGraphicsView : public QGraphicsView {
protected:
void drawBackground(QPainter *painter, const QRectF &rect) override {
QGraphicsView::drawBackground(painter, rect);
// 绘制网格
qreal left = int(rect.left()) - (int(rect.left()) % 20);
qreal top = int(rect.top()) - (int(rect.top()) % 20);
QVarLengthArray<QLineF, 100> lines;
for (qreal x = left; x < rect.right(); x += 20)
lines.append(QLineF(x, rect.top(), x, rect.bottom()));
for (qreal y = top; y < rect.bottom(); y += 20)
lines.append(QLineF(rect.left(), y, rect.right(), y));
painter->setPen(QPen(QColor(200, 200, 200), 0));
painter->drawLines(lines.data(), lines.size());
}
};
四、性能建议
- 避免在
paint()中做复杂计算,应提前缓存。 - 使用
QGraphicsItem::setCacheMode(QGraphicsItem::DeviceCoordinateCache)提升渲染速度。 - 对于大量静态项,考虑合并为一个
QGraphicsItem(如用QPicture)。 - 启用 OpenGL(可选):
view.setViewport(new QOpenGLWidget);
五、常见应用场景
- 流程图/拓扑图编辑器
- 2D 地图/平面图展示
- 可视化建模工具(如 UML、电路图)
- 游戏地图编辑器
六、参考资料
- Qt 官方文档 - Graphics View Framework
- 《C++ GUI Programming with Qt 6》第 13 章
如果你有具体需求(比如实现拖拽、自定义 item、多视图同步等),可以告诉我,我可以给出针对性代码示例。
5.QGraphicsItem
QGraphicsItem 是 Qt 框架中用于 2D 图形场景(QGraphicsScene)中的基本图形项类,是所有可放置在 QGraphicsScene 中的图形对象的基类。它是 Qt Graphics View Framework 的核心组成部分之一。
一、概述
Qt 的 Graphics View Framework 由三部分组成:
- View(视图):
QGraphicsView—— 用于显示场景。 - Scene(场景):
Q/GraphicsScene—— 容纳并管理图形项。 - Item(图形项):
QGraphicsItem及其子类 —— 实际绘制的内容。
QGraphicsItem 本身是一个抽象基类,通常需要继承它来自定义图形项,或者直接使用 Qt 提供的内置子类,如:
QGraphicsRectItemQGraphicsEllipseItemQGraphicsLineItemQGraphicsPixmapItemQGraphicsTextItemQGraphicsPathItem
二、核心功能
1. 坐标系统
- 本地坐标(Local Coordinates):每个
QGraphicsItem都有自己的坐标系,原点 (0,0) 通常是其“中心”或左上角(取决于实现)。 - 场景坐标(Scene Coordinates):所有项在
QGraphicsScene中的位置。 - 视图坐标(View Coordinates):对应于屏幕像素。
可通过以下函数转换坐标:
QPointF mapToScene(const QPointF &point) const;
QPointF mapFromScene(const QPointF &point) const;
QPointF mapToParent(const QPointF &point) const;
QPointF mapFromParent(const QPointF &point) const;
2. 位置与变换
setPos(x, y)/pos():设置/获取在父项或场景中的位置。- 支持旋转(
setRotation())、缩放(setScale())、剪切等仿射变换。 - 变换基于
QTransform,通过setTransform()可自定义。
3. 绘制(Painting)
必须重写以下纯虚函数(如果自定义项):
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
同时需实现:
QRectF boundingRect() const override;
⚠️ 注意:
boundingRect()必须返回该项在本地坐标系中包围盒(包括所有可能绘制内容),用于裁剪和碰撞检测。
可选重写:
QPainterPath shape() const; // 更精确的点击/碰撞区域,默认返回 boundingRect 的路径
4. 交互与事件
QGraphicsItem 支持鼠标、键盘、拖拽等事件,例如:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
要启用 hover 事件,需设置:
setAcceptHoverEvents(true);
要接收键盘事件,需:
setFlag(QGraphicsItem::ItemIsFocusable, true);
5. 父子关系与 Z 顺序
- 项可以有父子关系:子项随父项移动、旋转。
- 使用
setZValue()控制绘制顺序(值越大越靠前)。 - 默认情况下,添加顺序决定 Z 顺序,但可手动调整。
6. 碰撞检测
collidesWithItem()/collidesWithPath()- 基于
shape()路径进行精确检测(比boundingRect()更准)
三、常用标志(Flags)
通过 setFlag() 设置行为:
setFlag(QGraphicsItem::ItemIsMovable); // 可拖动
setFlag(QGraphicsItem::ItemIsSelectable); // 可被选中
setFlag(QGraphicsItem::ItemIsFocusable); // 可获得焦点
setFlag(QGraphicsItem::ItemClipsToShape); // 裁剪到 shape()
setFlag(QGraphicsItem::ItemSendsGeometryChanges); // 位置/变换改变时触发 itemChange
四、自定义 QGraphicsItem 示例
// myitem.h
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsItem>
#include <QPainter>
class MyItem : public QGraphicsItem
{
public:
MyItem();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
};
#endif // MYITEM_H
// myitem.cpp
#include "myitem.h"
#include <QGraphicsSceneMouseEvent>
#include <QCursor>
MyItem::MyItem()
{
setFlag(ItemIsMovable);
setFlag(ItemIsSelectable);
setAcceptHoverEvents(true);
}
QRectF MyItem::boundingRect() const
{
return QRectF(-20, -20, 40, 40); // 以 (0,0) 为中心的正方形
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
painter->setPen(Qt::black);
if (option->state & QStyle::State_Selected)
painter->setBrush(Qt::red);
else
painter->setBrush(Qt::blue);
painter->drawRect(boundingRect());
}
void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
qDebug() << "Item clicked at:" << event->pos();
QGraphicsItem::mousePressEvent(event);
}
使用方式:
QGraphicsScene scene;
MyItem *item = new MyItem();
scene.addItem(item);
item->setPos(100, 100);
QGraphicsView view(&scene);
view.show();
五、性能优化建议
- 尽量缩小
boundingRect()范围。 - 对复杂图形,使用
QGraphicsItemGroup或缓存(setCacheMode(DeviceCoordinateCache))。 - 避免在
paint()中做耗时操作。 - 使用
prepareGeometryChange()在修改几何前通知场景。
六、常见子类速查
| 类名 | 用途 |
|---|---|
QGraphicsRectItem |
矩形 |
QGraphicsEllipseItem |
椭圆/圆 |
QGraphicsLineItem |
直线 |
QGraphicsPixmapItem |
图像 |
QGraphicsTextItem |
文本 |
QGraphicsPathItem |
自定义路径 |
QGraphicsPolygonItem |
多边形 |
七、参考资料
- Qt 官方文档 - QGraphicsItem
- 《C++ GUI Programming with Qt 6》第 8 章
- Qt Examples:
graphicsview/目录下的示例(如elasticnodes,diagramscene)
如果你有具体需求(比如实现可拖拽连线、自定义动画项、与 OpenGL 结合等),可以继续提问!
6.QGraphicsRectItem
QGraphicsRectItem 是 Qt 框架中用于在 QGraphicsScene 中表示矩形图元(graphics item)的一个类。它是 QGraphicsItem 的子类,专门用于绘制矩形、正方形或带圆角的矩形。
一、基本介绍
- 头文件:
#include <QGraphicsRectItem> - 继承关系:
QGraphicsRectItem←QAbstractGraphicsShapeItem←QGraphicsItem - 功能:提供一个可自定义位置、大小、颜色、边框等属性的矩形图元,常用于图形编辑器、流程图、UI 设计工具等场景。
二、构造函数
// 默认构造,矩形为 (0, 0, 0, 0)
QGraphicsRectItem(QGraphicsItem *parent = nullptr);
// 指定矩形区域(x, y, width, height)
QGraphicsRectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = nullptr);
// 使用 QRectF 构造
QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = nullptr);
注意:
x和y是相对于图元自身坐标系的左上角位置(即局部坐标),不是场景坐标。
三、常用成员函数
1. 设置/获取矩形区域
void setRect(const QRectF &rect);
void setRect(qreal x, qreal y, qreal width, qreal height);
QRectF rect() const;
2. 绘图相关(继承自 QAbstractGraphicsShapeItem)
void setPen(const QPen &pen); // 设置边框样式
void setBrush(const QBrush &brush); // 设置填充样式
QPen pen() const;
QBrush brush() const;
3. 其他通用属性(继承自 QGraphicsItem)
void setPos(qreal x, qreal y); // 设置在场景中的位置
void setFlag(GraphicsItemFlag flag, bool enabled = true); // 启用交互(如可选、可移动等)
void setZValue(qreal z); // 设置 Z 轴层级(控制重叠顺序)
四、示例代码
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 创建场景
QGraphicsScene scene;
scene.setSceneRect(-200, -200, 400, 400);
// 创建矩形图元
QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 50);
rect->setPen(QPen(Qt::black, 2));
rect->setBrush(QBrush(Qt::yellow));
// 启用交互
rect->setFlag(QGraphicsItem::ItemIsSelectable);
rect->setFlag(QGraphicsItem::ItemIsMovable);
// 添加到场景
scene.addItem(rect);
// 创建视图并显示
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.setWindowTitle("QGraphicsRectItem 示例");
view.resize(500, 500);
view.show();
return app.exec();
}
五、注意事项
-
坐标系统:
rect()定义的是图元的本地坐标。setPos()设置的是图元在场景中的位置。- 若你希望矩形中心位于 (100, 100),可以:
rect->setRect(-50, -25, 100, 50); // 以中心为原点 rect->setPos(100, 100);
-
性能:
- 对于大量静态矩形,考虑使用
QGraphicsItemGroup或自定义QGraphicsItem以提升性能。
- 对于大量静态矩形,考虑使用
-
信号与槽:
QGraphicsRectItem本身不发射信号。若需响应点击、移动等事件,可:- 重写
mousePressEvent等虚函数(需继承并自定义类); - 或通过
QGraphicsScene的信号(如selectionChanged())间接处理。
- 重写
六、扩展用法
- 圆角矩形:
QGraphicsRectItem本身不支持圆角。如需圆角,应使用QGraphicsPathItem+QPainterPath::addRoundedRect()。 - 动画:配合
QPropertyAnimation可对pos、rect等属性做动画(需注册元对象系统属性)。
七、相关类
| 类名 | 说明 |
|---|---|
QGraphicsEllipseItem |
椭圆/圆形图元 |
QGraphicsLineItem |
直线图元 |
QGraphicsTextItem |
文本图元 |
QGraphicsPathItem |
任意路径图元(更灵活) |
如需进一步实现交互逻辑(如拖拽改变大小),通常需要继承 QGraphicsRectItem 并重写鼠标事件处理函数。
如果你有具体需求(比如“如何让矩形可调整大小”或“如何响应点击事件”),欢迎继续提问!
更多推荐
所有评论(0)