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 必须在 QPaintDevicepaintEvent()(对 QWidget)或显式 begin/end 范围内使用。


二、Qt Graphics View Framework(高级图形视图框架)

适用于需要管理大量 2D 图形项、支持缩放/平移/交互的复杂场景(如流程图、CAD、游戏地图等)。

三大核心组件(MVC 架构思想)

组件 作用
Model(数据) QGraphicsScene 存储和管理所有图形项(QGraphicsItem 及其子类)
View(视图) QGraphicsView 提供可视化窗口,支持滚动、缩放、拖拽等交互
Item(元素) QGraphicsItem 场景中的基本图形单元(如矩形、文本、自定义图形)

核心类详解

1. QGraphicsItem(抽象基类)
  • 所有图形项的基类。
  • 子类包括:
    • QGraphicsRectItem
    • QGraphicsEllipseItem
    • QGraphicsTextItem
    • QGraphicsPixmapItem
    • QGraphicsPathItem
    • QGraphicsLineItem
    • QGraphicsPolygonItem
    • 以及可自定义的派生类(需重写 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 控制线条样式和填充样式,用于 QPainterQGraphicsItem
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。若要在其他地方绘图(如保存图像),可对 QImageQPixmap 创建 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::Antialiasing
  • QPainter::SmoothPixmapTransform
  • QPainter::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)

将内容绘制到 QImageQPixmap,可用于保存图像或预渲染:

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 对象的创建次数。
  • 利用 QRegionclipPath 限制重绘区域。

七、常见问题

Q: 为什么不在构造函数里用 QPainter?

A: 因为 widget 尚未完全初始化,且没有有效的绘制设备上下文。必须在 paintEvent() 或对 QImage/QPixmap 操作时使用。

Q: 如何强制重绘?

A: 调用 widget->update()(异步,高效)或 widget->repaint()(同步,慎用)。


八、参考文档


如果你有具体应用场景(如画曲线、图表、动画、打印等),可以进一步说明,我可以给出针对性示例。

3.QGraphicsScene

QGraphicsScene 是 Qt 框架中用于管理 2D 图形项(QGraphicsItem)的场景类,是 Qt Graphics View Framework 的核心组成部分之一。它与 QGraphicsView(视图)和 QGraphicsItem(图形项)共同构成一个强大的 2D 图形渲染与交互系统。


一、基本概念

  • QGraphicsScene:表示一个场景,用于容纳和管理大量的 2D 图形项(如矩形、椭圆、文本、自定义图形等)。
  • QGraphicsView:是一个可滚动的视口(viewport),用于显示 QGraphicsScene 的一部分。
  • QGraphicsItem:代表场景中的单个图形元素,可以是 Qt 提供的标准项(如 QGraphicsRectItemQGraphicsEllipseItem),也可以是自定义子类。

三者关系:

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. 动画支持

配合 QPropertyAnimationQGraphicsItemAnimation(旧版)实现动画。

2. 拖放(Drag & Drop)

重写 dragEnterEventdropEvent 等方法支持拖放操作。

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(),场景矩形是否包含该项
无法交互 确保设置了 ItemIsMovableItemIsSelectable 等标志
坐标混乱 理解局部坐标 vs 场景坐标,善用 mapToScene()
性能差 启用缓存、减少重绘、使用 BSP 索引

八、参考文档


如需进一步了解自定义图形项、动画、拖拽、缩放/平移控制等内容,可继续提问!

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、电路图)
  • 游戏地图编辑器

六、参考资料


如果你有具体需求(比如实现拖拽、自定义 item、多视图同步等),可以告诉我,我可以给出针对性代码示例。

5.QGraphicsItem

QGraphicsItem 是 Qt 框架中用于 2D 图形场景(QGraphicsScene)中的基本图形项类,是所有可放置在 QGraphicsScene 中的图形对象的基类。它是 Qt Graphics View Framework 的核心组成部分之一。


一、概述

Qt 的 Graphics View Framework 由三部分组成:

  1. View(视图)QGraphicsView —— 用于显示场景。
  2. Scene(场景)Q/GraphicsScene —— 容纳并管理图形项。
  3. Item(图形项)QGraphicsItem 及其子类 —— 实际绘制的内容。

QGraphicsItem 本身是一个抽象基类,通常需要继承它来自定义图形项,或者直接使用 Qt 提供的内置子类,如:

  • QGraphicsRectItem
  • QGraphicsEllipseItem
  • QGraphicsLineItem
  • QGraphicsPixmapItem
  • QGraphicsTextItem
  • QGraphicsPathItem

二、核心功能

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>
  • 继承关系QGraphicsRectItemQAbstractGraphicsShapeItemQGraphicsItem
  • 功能:提供一个可自定义位置、大小、颜色、边框等属性的矩形图元,常用于图形编辑器、流程图、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);

注意:xy 是相对于图元自身坐标系的左上角位置(即局部坐标),不是场景坐标。


三、常用成员函数

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();
}

五、注意事项

  1. 坐标系统

    • rect() 定义的是图元的本地坐标
    • setPos() 设置的是图元在场景中的位置
    • 若你希望矩形中心位于 (100, 100),可以:
      rect->setRect(-50, -25, 100, 50); // 以中心为原点
      rect->setPos(100, 100);
      
  2. 性能

    • 对于大量静态矩形,考虑使用 QGraphicsItemGroup 或自定义 QGraphicsItem 以提升性能。
  3. 信号与槽

    • QGraphicsRectItem 本身不发射信号。若需响应点击、移动等事件,可:
      • 重写 mousePressEvent 等虚函数(需继承并自定义类);
      • 或通过 QGraphicsScene 的信号(如 selectionChanged())间接处理。

六、扩展用法

  • 圆角矩形QGraphicsRectItem 本身不支持圆角。如需圆角,应使用 QGraphicsPathItem + QPainterPath::addRoundedRect()
  • 动画:配合 QPropertyAnimation 可对 posrect 等属性做动画(需注册元对象系统属性)。

七、相关类

类名 说明
QGraphicsEllipseItem 椭圆/圆形图元
QGraphicsLineItem 直线图元
QGraphicsTextItem 文本图元
QGraphicsPathItem 任意路径图元(更灵活)

如需进一步实现交互逻辑(如拖拽改变大小),通常需要继承 QGraphicsRectItem 并重写鼠标事件处理函数。

如果你有具体需求(比如“如何让矩形可调整大小”或“如何响应点击事件”),欢迎继续提问!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐