跳到主要内容Qt C++ 场景图架构核心类详解 | 极客日志C++
Qt C++ 场景图架构核心类详解
介绍 Qt C++ 场景图架构的核心类,涵盖 Graphics View Framework(2D)、Qt Quick(2D/3D)及 Qt 3D 模块。重点解析 QGraphicsScene、QGraphicsView、QGraphicsItem 等 2D 管理类,以及 QQuickWindow、QSGNode 等渲染节点。内容包含坐标系统、事件处理、性能优化建议及代码示例,适用于桌面应用、动态 UI 及三维渲染开发。
日志猎手13 浏览 Qt C++ 场景图架构核心类详解
在 Qt 的 C++ 场景图架构中,不同模块(如 Qt Widgets、Qt Quick、Qt 3D)提供了各自的场景图实现。核心类及其功能如下:
1. Qt Widgets - Graphics View 框架(2D 场景图)
- QGraphicsScene:场景容器,管理所有图形项(
QGraphicsItem),负责碰撞检测、事件分发、打印渲染等。支持动态添加/删除项,通过 addItem()、removeItem() 管理。
- QGraphicsView:视图窗口,显示场景内容。支持缩放、平移、旋转(通过
transform()),处理鼠标/键盘事件并映射到场景坐标。可启用 OpenGL 加速(通过 setViewport(QOpenGLWidget*))。
- QGraphicsItem:图形项基类,包括:
- 预定义项:
QGraphicsRectItem(矩形)、QGraphicsEllipseItem(椭圆)、QGraphicsPixmapItem(图片)、QGraphicsTextItem(文本)、QGraphicsPathItem(路径)等。
- 自定义项:继承
QGraphicsItem 并重写 boundingRect()(边界矩形)和 paint()(绘制逻辑),支持拖拽、选择、分组(QGraphicsItemGroup)。
- 辅助类:
QGraphicsProxyWidget:嵌入 QWidget 到场景中(如按钮、输入框)。
QGraphicsLayout/QGraphicsLayoutItem:布局管理(如水平/垂直布局)。
QGraphicsScene::BspTreeIndex:通过二进制空间划分树优化大规模项的碰撞检测。
2. 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)策略。
六、常见问题
| 问题 | 解决方案 |
|---|
| 图形项不显示 | 检查是否调用了 addItem(),场景矩形是否包含该项 |
| 无法交互 | 确保设置了 ItemIsMovable、ItemIsSelectable 等标志 |
| 坐标混乱 | 理解局部坐标 vs 场景坐标,善用 mapToScene() |
| 性能差 | 启用缓存、减少重绘、使用 BSP 索引 |
七、参考文档
3. 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);
view.resetTransform();
view.centerOn(400, 300);
更灵活的方式:重写 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. 背景与网格(自定义绘制)
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)。
view.setViewport(new QOpenGLWidget);
五、常见应用场景
- 流程图/拓扑图编辑器
- 2D 地图/平面图展示
- 可视化建模工具(如 UML、电路图)
- 游戏地图编辑器
六、参考资料
4. QGraphicsItem
QGraphicsItem 是 Qt 框架中用于 2D 图形场景(QGraphicsScene)中的基本图形项类,是所有可放置在 QGraphicsScene 中的图形对象的基类。它是 Qt Graphics View Framework 的核心组成部分之一。
一、概述
Qt 的 Graphics View Framework 由三部分组成:
- View(视图):
QGraphicsView —— 用于显示场景。
- Scene(场景):
QGraphicsScene —— 容纳并管理图形项。
- 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;
4. 交互与事件
QGraphicsItem 支持鼠标、键盘、拖拽等事件,例如:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
setAcceptHoverEvents(true);
setFlag(QGraphicsItem::ItemIsFocusable, true);
5. 父子关系与 Z 顺序
- 项可以有父子关系:子项随父项移动、旋转。
- 使用
setZValue() 控制绘制顺序(值越大越靠前)。
- 默认情况下,添加顺序决定 Z 顺序,但可手动调整。
6. 碰撞检测
collidesWithItem() / collidesWithPath()
- 基于
shape() 路径进行精确检测(比 boundingRect() 更准)
三、常用标志(Flags)
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
setFlag(QGraphicsItem::ItemIsFocusable);
setFlag(QGraphicsItem::ItemClipsToShape);
setFlag(QGraphicsItem::ItemSendsGeometryChanges);
四、自定义 QGraphicsItem 示例
#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
#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);
}
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)
5. QGraphicsRectItem
QGraphicsRectItem 是 Qt 框架中用于在 QGraphicsScene 中表示矩形图元(graphics item)的一个类。它是 QGraphicsItem 的子类,专门用于绘制矩形、正方形或带圆角的矩形。
一、基本介绍
- 头文件:
#include <QGraphicsRectItem>
- 继承关系:
QGraphicsRectItem ← QAbstractGraphicsShapeItem ← QGraphicsItem
- 功能:提供一个可自定义位置、大小、颜色、边框等属性的矩形图元,常用于图形编辑器、流程图、UI 设计工具等场景。
二、构造函数
QGraphicsRectItem(QGraphicsItem *parent = nullptr);
QGraphicsRectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = nullptr);
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);
四、示例代码
#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() 设置的是图元在场景中的位置。
- 性能:
- 对于大量静态矩形,考虑使用
QGraphicsItemGroup 或自定义 QGraphicsItem 以提升性能。
- 信号与槽:
QGraphicsRectItem 本身不发射信号。若需响应点击、移动等事件,可:
- 重写
mousePressEvent 等虚函数(需继承并自定义类);
- 或通过
QGraphicsScene 的信号(如 selectionChanged())间接处理。
若你希望矩形中心位于 (100, 100),可以:
rect->setRect(-50, -25, 100, 50);
rect->setPos(100, 100);
六、扩展用法
- 圆角矩形:
QGraphicsRectItem 本身不支持圆角。如需圆角,应使用 QGraphicsPathItem + QPainterPath::addRoundedRect()。
- 动画:配合
QPropertyAnimation 可对 pos、rect 等属性做动画(需注册元对象系统属性)。
七、相关类
| 类名 | 说明 |
|---|
QGraphicsEllipseItem | 椭圆/圆形图元 |
QGraphicsLineItem | 直线图元 |
QGraphicsTextItem | 文本图元 |
QGraphicsPathItem | 任意路径图元(更灵活) |
6. QQuickWindow
QQuickWindow 是 Qt Quick 模块中的一个关键类,用于显示基于 QML(Qt Meta-Object Language)构建的用户界面。它是 QWindow 的子类,专为渲染 Qt Quick 内容而设计。
基本介绍
- 头文件:
#include <QQuickWindow>
- 继承关系:
QQuickWindow ← QWindow ← QObject
- 所属模块:
QtQuick
QQuickWindow 提供了一个窗口,可以加载并显示一个 QQuickItem(通常是 QQuickView 的根项或直接设置的 contentItem)。它负责管理场景图(Scene Graph)的渲染、事件处理、动画调度等。
常见用法
1. 创建 QQuickWindow 并加载 QML
#include <QGuiApplication>
#include <QQuickWindow>
#include <QQmlEngine>
#include <QQmlComponent>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQuickWindow window;
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:/main.qml"));
QObject *obj = component.create();
if (auto item = qobject_cast<QQuickItem*>(obj)) {
window.setContentItem(item);
}
window.show();
return app.exec();
}
注意:通常更常见的是使用 QQuickView(继承自 QQuickWindow),它封装了加载 QML 文件的逻辑。
2. 使用 QQuickView(推荐方式)
#include <QGuiApplication>
#include <QQuickView>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}
核心特性
- Scene Graph 渲染:
QQuickWindow 使用高效的场景图系统进行 GPU 加速渲染。
- 事件处理:支持鼠标、键盘、触摸、拖拽等事件,并将它们传递给 QML 中的对象。
- 多线程渲染:默认启用渲染线程(可配置),提升 UI 流畅度。
- 透明窗口支持:可通过
setFormat() 和 setColor(Qt::transparent) 实现透明背景。
- 帧同步与动画:集成 Qt 的动画系统,每帧自动更新。
常用方法
| 方法 | 说明 |
|---|
setContentItem(QQuickItem *item) | 设置窗口显示的根 QML 项 |
contentItem() | 获取当前内容项 |
setPersistentSceneGraph(bool) | 控制场景图是否在隐藏时保留 |
scheduleRenderJob(...) | 调度自定义渲染任务 |
resetOpenGLState() | 在混合 OpenGL 渲染时重置状态 |
注意事项
QQuickWindow 本身不自动加载 QML 文件,需手动创建 QQmlComponent 或使用 QQuickView。
- 若需与 QWidget 混合使用,应考虑
QWidget::createWindowContainer() 包装 QQuickWindow。
- 在嵌入式或无窗口系统(如 EGLFS)中,
QQuickWindow 是主要的 UI 显示载体。
7. QSGNode
QSGNode 是 Qt Quick Scene Graph(场景图)系统中的一个核心类,用于表示场景图中的节点。Qt Quick 使用场景图(Scene Graph)作为其底层渲染架构,以高效地渲染用户界面。QSGNode 是所有场景图节点的基类。
基本概念
- 场景图(Scene Graph):一种树状结构,用于描述 UI 的视觉内容。每个节点代表屏幕上的一个可视元素或一组操作(如变换、裁剪等)。
- QSGNode:抽象基类,不直接实例化,而是通过其子类(如
QSGGeometryNode、QSGTransformNode、QSGClipNode 等)来构建具体的渲染内容。
主要子类
| 子类 | 用途 |
|---|
QSGGeometryNode | 表示具有几何形状和材质(着色器/纹理)的可渲染对象,常用于自定义绘制。 |
QSGTransformNode | 应用仿射变换(如平移、旋转、缩放)到其子节点。 |
QSGClipNode | 定义裁剪区域,限制子节点的绘制范围。 |
QSGRootNode | 场景图的根节点。 |
QSGOpacityNode | 控制子树的透明度。 |
典型使用场景
- 性能优化
场景图在渲染线程中运行,与 UI 线程分离。正确使用 QSGNode 可以避免不必要的重建,提升性能。
自定义 QQuickItem 渲染
当你继承 QQuickItem 并重写 updatePaintNode() 方法时,需要返回一个 QSGNode*(通常是 QSGGeometryNode),用于描述如何渲染该 Item。
QSGNode *MyItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) {
QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode);
if (!node) {
node = new QSGGeometryNode;
}
return node;
}
注意事项
- 线程安全:
QSGNode 及其子类通常在渲染线程中访问,因此在 UI 线程中修改节点时需谨慎(通常通过 updatePaintNode 安全地同步)。
- 内存管理:Qt Quick 负责管理场景图节点的生命周期,一般不需要手动 delete。
- 不要跨帧复用未更新的节点:若内容未变,可返回旧节点以提升效率;若内容变化,必须更新节点数据。
8. QQuickItem
QQuickItem 是 Qt Quick 模块中的一个核心类,用于表示 Qt Quick 场景图(Scene Graph)中的可视项(visual item)。它是所有可视 QML 元素(如 Rectangle、Image、Text 等)在 C++ 层的基类。
基本信息
- 头文件:
#include <QQuickItem>
- 继承自:
QObject
- 派生类:
QQuickPaintedItem、QQuickFramebufferObject、自定义 QML 类型等
- 模块:
Qt Quick
主要功能
- 可视元素的基础
所有在 QML 中可见的元素(除了非可视元素如 Timer、Behavior)都对应一个 QQuickItem 实例。
- 坐标系统与变换
- 提供
x, y, width, height 等属性。
- 支持旋转(
rotation)、缩放(scale)、变换原点(transformOrigin)等。
- 支持父子坐标转换(
mapToItem(), mapFromItem())。
- 事件处理
可重写以下虚函数以响应用户交互:
mousePressEvent(QMouseEvent *)
mouseMoveEvent(QMouseEvent *)
touchEvent(QTouchEvent *)
hoverEnterEvent(QHoverEvent *)
keyPressEvent(QKeyEvent *)(需先设置 focus: true)
- 绘制支持
- 默认不直接绘制内容(由场景图自动处理)。
- 若需自定义绘制,可继承
QQuickPaintedItem 并重写 paint() 方法(使用 QPainter)。
- 更高性能的方式是直接操作场景图(通过
updatePaintNode()),但这更复杂。
- 与 QML 交互
- 可通过
qmlRegisterType() 将 C++ 类注册为 QML 类型。
- 使用
Q_PROPERTY 暴露属性到 QML。
- 使用
Q_INVOKABLE 或 Q_SLOT 暴露方法。
示例:自定义 QQuickItem(使用 QQuickPaintedItem)
#include <QQuickPaintedItem>
#include <QColor>
class MyItem : public QQuickPaintedItem {
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
public:
MyItem(QQuickItem *parent = nullptr) : QQuickPaintedItem(parent) {}
void paint(QPainter *painter) override { painter->fillRect(boundingRect(), m_color); }
QColor color() const { return m_color; }
void setColor(const QColor &c) {
if (m_color != c) {
m_color = c;
emit colorChanged();
update();
}
}
signals:
void colorChanged();
private:
QColor m_color = Qt::red;
};
qmlRegisterType<MyItem>("MyModule", 1, 0, "MyItem");
import MyModule 1.0
MyItem {
width: 100
height: 100
color: "blue"
}
注意事项
- 线程安全:
QQuickItem 的大多数方法应在 GUI 线程中调用。
- 性能:频繁调用
update() 或在 paint() 中做复杂计算会影响性能。
- 父子关系:
QQuickItem 支持父子结构,子项的坐标相对于父项。
9. Qt Quick 3D
Qt Quick 3D 是 Qt 框架中的一个模块,用于在 Qt Quick 应用程序中创建和渲染 3D 内容。它将 3D 图形与 Qt Quick 的声明式 UI 编程模型无缝集成,使开发者能够使用 QML(Qt Meta-Object Language)轻松构建具有 3D 元素的现代用户界面。
核心特性
- 基于 Qt Quick 的 3D 渲染
- 使用熟悉的 QML 语法定义 3D 场景。
- 支持与 2D Qt Quick 元素混合(例如叠加按钮、文本等)。
- 基于物理的渲染(PBR)
- 支持金属度/粗糙度工作流。
- 提供逼真的材质和光照效果。
- 内置 3D 资源支持
- 可导入
.mesh(Qt 自定义格式)、.gltf / .glb(推荐)、.obj 等模型。
- 支持纹理、法线贴图、环境光遮蔽等。
- 动画与交互
- 通过
PropertyAnimation、NumberAnimation 等对 3D 对象属性(如位置、旋转)进行动画。
- 支持鼠标/触摸交互(如旋转、缩放模型)。
- 自定义着色器(可选)
- 支持使用 Effect、ShaderEffect 等编写自定义 GLSL 着色器。
- 跨平台
- 支持 Windows、macOS、Linux、Android、iOS 等,依赖 OpenGL ES 或 Vulkan(取决于平台)。
基本 QML 示例
import QtQuick
import QtQuick.Window
import QtQuick3D
Window {
width: 800
height: 600
visible: true
title: "Qt Quick 3D 示例"
View3D {
anchors.fill: parent
camera: camera
PerspectiveCamera {
id: camera
position: Qt.vector3d(0, 0, 600)
}
DirectionalLight {
position: Qt.vector3d(500, 500, 500)
color: "#ffffff"
brightness: 1.0
}
Model {
source: "#Cube" // 内置立方体
position: Qt.vector3d(0, 0, 0)
scale: Qt.vector3d(200, 200, 200)
materials: DefaultMaterial {
diffuseColor: "steelblue"
}
}
}
}
常用组件
| 组件 | 说明 |
|---|
View3D | 3D 渲染视口 |
PerspectiveCamera / OrthographicCamera | 相机类型 |
Model | 表示 3D 模型(可加载外部文件或使用内置形状) |
DefaultMaterial / PrincipledMaterial | 材质系统(后者支持完整 PBR) |
DirectionalLight / PointLight / SpotLight | 光源类型 |
导入外部模型(如 glTF)
Model {
source: "models/car.glb"
materials: PrincipledMaterial {
baseColor: "red"
metalness: 0.8
roughness: 0.2
}
}
注意:需确保模型路径正确,并在 .pro 文件中包含资源(若打包进应用)。
性能提示
- 避免每帧更新复杂几何体。
- 使用实例化(
InstanceList)渲染大量相同对象。
- 合理设置
View3D 的 renderMode(如 Overlay vs Underlay)。
学习资源
- Qt 官方文档 - Qt Quick 3D
- Qt Creator 内置的 3D Examples(如
simple3d, dynamicmaterials, instancing)
- Qt Design Studio(可视化设计 3D 场景)
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online