QT:QT场景视图
简介
在 Qt 中,场景视图框架(Scene - View Framework)提供了一个强大且灵活的方式来管理和显示 2D 图形元素。该框架主要由三个核心类组成:QGraphicsScene、QGraphicsView 和 QGraphicsItem,它们协同工作以实现复杂的 2D 图形界面。
核心类介绍
QGraphicsScene:场景类,作为一个容器,用于管理大量的 QGraphicsItem 对象。它不直接显示图形,而是负责存储和组织这些图形项,提供对图形项的添加、删除、查找等操作,同时处理图形项的碰撞检测、鼠标事件等。
QGraphicsView:视图类,它是一个可视化的窗口,用于显示 QGraphicsScene 中的内容。可以对视图进行缩放、平移、旋转等操作,还能处理用户的交互事件,如鼠标点击、滚动等。
QGraphicsItem:图形项类,是所有图形元素的基类。可以通过继承 QGraphicsItem 来创建自定义的图形项,如矩形、椭圆、文本等,每个图形项可以有自己的属性(如颜色、大小、位置等)和行为(如鼠标交互)。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建场景
QGraphicsScene scene;
// 创建矩形项
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 50);
rectItem->setBrush(Qt::red);
// 将矩形项添加到场景中
scene.addItem(rectItem);
// 创建椭圆项
QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem(150, 20, 80, 60);
ellipseItem->setBrush(Qt::blue);
// 将椭圆项添加到场景中
scene.addItem(ellipseItem);
// 创建视图
QGraphicsView view(&scene);
view.setWindowTitle("Qt Scene - View Example");
view.resize(400, 300);
view.show();
return app.exec();
}
头文件包含:
QApplication:用于管理 Qt 应用程序的资源和事件循环。
QGraphicsScene:场景类,用于管理图形项。
QGraphicsView:视图类,用于显示场景内容。
QGraphicsRectItem 和 QGraphicsEllipseItem:分别用于创建矩形和椭圆图形项。
创建一个 QGraphicsScene 对象,作为图形项的容器。
创建一个红色的矩形项和一个蓝色的椭圆项,并使用 addItem 方法将它们添加到场景中。
创建一个 QGraphicsView 对象,将场景指针传递给它,设置窗口标题和大小,然后显示视图
看到一个窗口,其中显示了一个红色的矩形和一个蓝色的椭圆,这就是使用 Qt 场景视图框架创建的简单图形界面。
QGraphicsLineItem
用于绘制直线。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsLineItem>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsLineItem *lineItem = new QGraphicsLineItem(20, 20, 200, 20);
lineItem->setPen(QPen(Qt::blue, 2));
scene.addItem(lineItem);
QGraphicsView view(&scene);
view.show();
return app.exec();
}
QGraphicsPathItem
用于绘制任意形状的路径,可以通过 QPainterPath 来定义复杂的图形。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPathItem>
#include <QPainterPath>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
QPainterPath path;
path.moveTo(50, 50);
path.lineTo(100, 100);
path.lineTo(150, 50);
QGraphicsPathItem *pathItem = new QGraphicsPathItem(path);
pathItem->setBrush(Qt::yellow);
pathItem->setPen(QPen(Qt::red, 2));
scene.addItem(pathItem);
QGraphicsView view(&scene);
view.show();
return app.exec();
}
QGraphicsPolygonItem
用于绘制多边形。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPolygonItem>
#include <QPolygonF>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
QPolygonF polygon;
polygon << QPointF(50, 50) << QPointF(100, 100) << QPointF(150, 50);
QGraphicsPolygonItem *polygonItem = new QGraphicsPolygonItem(polygon);
polygonItem->setBrush(Qt::green);
polygonItem->setPen(QPen(Qt::black, 2));
scene.addItem(polygonItem);
QGraphicsView view(&scene);
view.show();
return app.exec();
}
QGraphicsTextItem
用于显示文本
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsTextItem>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsTextItem *textItem = new QGraphicsTextItem("Hello, Qt!");
textItem->setFont(QFont("Arial", 20));
scene.addItem(textItem);
QGraphicsView view(&scene);
view.show();
return app.exec();
}
QGraphicsItemGroup
用于将多个图形项组合成一个单一的图形项,方便对一组图形进行统一操作,如移动、旋转等。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
#include <QGraphicsItemGroup>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem(60, 0, 50, 50);
QGraphicsItemGroup *group = new QGraphicsItemGroup;
group->addToGroup(rectItem);
group->addToGroup(ellipseItem);
scene.addItem(group);
QGraphicsView view(&scene);
view.show();
return app.exec();
}
自由拖动图形
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QMouseEvent>
#include <QGraphicsSceneMouseEvent>
// 自定义可拖动矩形图形项类
class DraggableRectItem : public QGraphicsRectItem {
public:
DraggableRectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = nullptr)
: QGraphicsRectItem(x, y, width, height, parent), isDragging(false) {
// 开启图形项的鼠标交互属性
setFlags(ItemIsMovable | ItemIsSelectable);
}
protected:
// 鼠标按下事件处理函数
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
if (event->button() == Qt::LeftButton) {
// 记录鼠标按下时的位置
lastMousePos = event->scenePos();
isDragging = true;
}
QGraphicsRectItem::mousePressEvent(event);
}
// 鼠标移动事件处理函数
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override {
if (isDragging) {
// 计算鼠标在场景中的水平位移
qreal dx = event->scenePos().x() - lastMousePos.x();
// 只处理左右方向的拖动
moveBy(dx, 0);
// 更新上次鼠标位置
lastMousePos = event->scenePos();
}
QGraphicsRectItem::mouseMoveEvent(event);
}
// 鼠标释放事件处理函数
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override {
if (event->button() == Qt::LeftButton) {
isDragging = false;
}
QGraphicsRectItem::mouseReleaseEvent(event);
}
private:
bool isDragging;
QPointF lastMousePos;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建场景
QGraphicsScene scene;
// 创建可拖动的矩形图形项
DraggableRectItem *rectItem = new DraggableRectItem(50, 50, 100, 50);
rectItem->setBrush(Qt::blue);
// 将矩形图形项添加到场景中
scene.addItem(rectItem);
// 创建视图
QGraphicsView view(&scene);
view.setWindowTitle("Draggable Rectangle");
view.resize(400, 300);
view.show();
return app.exec();
}
在 DraggableRectItem 的构造函数中添加了 setFlags(ItemIsMovable | ItemIsSelectable);,这行代码开启了图形项的鼠标交互属性,使得图形项能够接收鼠标事件并进行相应的处理。这样修改后,矩形应该可以跟随鼠标左右拖动了。
QT 自定义图元实现鼠标左键:拖拽 鼠标滚动:拉伸 鼠标右键:旋转
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QMouseEvent>
#include <QWheelEvent>
// 添加 QGraphicsSceneMouseEvent 头文件
#include <QGraphicsSceneMouseEvent>
// 自定义图元类
class CustomGraphicsItem : public QGraphicsItem
{
public:
CustomGraphicsItem(QGraphicsItem *parent = nullptr) : QGraphicsItem(parent)
{
setFlags(ItemIsMovable | ItemIsSelectable);
m_scale = 1.0;
m_rotation = 0.0;
}
// 定义图元的边界矩形
QRectF boundingRect() const override
{
return QRectF(-50, -50, 100, 100);
}
// 绘制图元
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::blue);
painter->setBrush(Qt::lightGray);
painter->scale(m_scale, m_scale);
painter->rotate(m_rotation);
painter->drawRect(-50, -50, 100, 100);
}
protected:
// 鼠标按下事件处理
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
{
if (event->button() == Qt::LeftButton)
{
m_dragStartPos = event->pos();
}
QGraphicsItem::mousePressEvent(event);
}
// 鼠标移动事件处理
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
{
if (event->buttons() & Qt::LeftButton)
{
QPointF delta = event->pos() - m_dragStartPos;
moveBy(delta.x(), delta.y());
}
QGraphicsItem::mouseMoveEvent(event);
}
// 鼠标滚轮事件处理
void wheelEvent(QGraphicsSceneWheelEvent *event) override
{
if (event->delta() > 0)
{
m_scale *= 1.1;
}
else
{
m_scale /= 1.1;
}
update();
QGraphicsItem::wheelEvent(event);
}
// 鼠标右键释放事件处理
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
{
if (event->button() == Qt::RightButton)
{
m_rotation += 15;
update();
}
QGraphicsItem::mouseReleaseEvent(event);
}
private:
QPointF m_dragStartPos;
qreal m_scale;
qreal m_rotation;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 创建场景和视图
QGraphicsScene scene;
QGraphicsView view(&scene);
// 创建自定义图元并添加到场景中
CustomGraphicsItem *item = new CustomGraphicsItem;
scene.addItem(item);
// 显示视图
view.show();
return a.exec();
}
CustomGraphicsItem 类
构造函数:初始化图元的可移动和可选择属性,并设置初始的缩放比例和旋转角度。
boundingRect 函数:定义图元的边界矩形,用于确定图元的绘制范围。
paint 函数:使用 QPainter 绘制图元,应用当前的缩放和旋转变换。
mousePressEvent 函数:当鼠标左键按下时,记录鼠标的起始位置。
mouseMoveEvent 函数:当鼠标左键按住并移动时,根据鼠标的位移移动图元。
wheelEvent 函数:处理鼠标滚轮事件,根据滚轮的滚动方向进行缩放操作。
mouseReleaseEvent 函数:当鼠标右键释放时,将图元旋转 15 度。
2. main 函数
创建 QApplication 对象,用于管理应用程序的事件循环。
创建 QGraphicsScene 和 QGraphicsView 对象。
创建 CustomGraphicsItem 对象并添加到场景中。
显示视图并启动应用程序的事件循环。