Qt学习:图形视图框架的使用

news2024/11/27 10:25:38

文章目录

  • 前言
  • 一、场景、视图和图形项的介绍
  • 二、图形视图框架的坐标系统
  • 三、图形视图框架的事件处理
  • 四、示例完整代码
  • 五、QtCreator官方示例
  • 总结


前言

近期重温了一下Qt中的图形视图框架,这里将所学习的内容进行记录总结。这个框架提供了一个基于图形项的模型视图编程方法,主要有场景、视图和图形项三部分组成,下面结合示例进行展示,希望可以帮助到大家,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、场景、视图和图形项的介绍

图形视图框架由以下三个部分组成:场景QGraphicsScene视图QGraphicsView图形项QGraphicsItem

QGraphicsScene:该类提供了图形视图框架中的场景,是图形项对象的容器,拥有以下功能
1.提供用于管理大量图形项的高速接口
2.传播事件到每一个图形项
3.管理图形项的状态,比如选择和处理焦点
4.提供无变换的渲染功能,主要用于打印

QGraphicsView:该类提供了视图部件,用来显示场景中的内容
1.可以连接多个视图到同一个场景,为相同的数据集提供多个视口
2.视图部件是一个可滚动的区域,提供了一个滚动条来浏览大的场景
3.通过setDragMode(QGraphicsView::ScrollHandDrag)将光标变为手掌形状,可以拖动场景
4.通过setDragMode(QGraphicsView::RubberBandDrag)实现鼠标拖出矩形框来选择场景中的图形项
5.通过setViewport()设置QOpenGLWidget作为视口,使用OpenGL进行渲染

QGraphicsItem:该类是场景中图形项的基类,在图形视图框架中有提供一些典型形状的图形项
1.鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件
2.键盘输入焦点和键盘事件
3.拖放事件
4.使用QGraphicsItemGroup实现分组
5.碰撞检测

二、图形视图框架的坐标系统

图形视图框架中有三个有效的坐标系统:场景坐标视图坐标图形项坐标,这三个坐标系统可以通过特定函数进行坐标映射

场景坐标:场景坐标是所有图形项的基础坐标系统,其原点在场景的中心,x和y坐标分别向右和向下增大
视图坐标:视图坐标就是视图部件的坐标,原点在QGraphicsView视口的左上角,x和y坐标分别向右和向下增大
图形项坐标:图形项使用自己的本地坐标系统,坐标通常是以它们的中心为原点(0,0),而这也是所有变换的中心
坐标映射:实现坐标变换,不仅可以在视图、场景和图形项之间使用坐标映射,还可以在父子图形项等之间进行映射:
这里是坐标映射函数表格:
请添加图片描述

可以将我的示例中的pro文件内容修改为下面这样,来运行示例1,通过查看打印结果,直观的了解各坐标系统

#条件编译
DEFINES += EXAMPLE_1
#DEFINES += EXAMPLE_2

三、图形视图框架的事件处理

图形视图框架中的事件都是先由视图进行接收,然后传递给场景,再由场景传递给相应的图形项

1.键盘事件和图形效果:这里对图形项的键盘按下事件进行处理,并为图形项添加图形效果

//键盘按下事件处理,移动图形项
void MyItem::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    //移动图形项
    case Qt::Key_Up:   //上移
    {
        moveBy(0,-10);
        break;
    }
    case Qt::Key_Down:   //下移
    {
        moveBy(0,10);
        break;
    }
    case Qt::Key_Left:   //左移
    {
        moveBy(-10,0);
        break;
    }
    case Qt::Key_Right:   //右移
    {
        moveBy(10,0);
        break;
    }

    //添加图形效果
    case Qt::Key_1:   //模糊效果
    {
        QGraphicsBlurEffect *blurEffect = new QGraphicsBlurEffect;
        blurEffect->setBlurHints(QGraphicsBlurEffect::QualityHint);
        blurEffect->setBlurRadius(8);
        setGraphicsEffect(blurEffect);
        break;
    }
    case Qt::Key_2:   //染色效果
    {
        QGraphicsColorizeEffect *ColorizeEffect = new QGraphicsColorizeEffect;
        ColorizeEffect->setColor(Qt::white);
        ColorizeEffect->setStrength(0.6);
        setGraphicsEffect(ColorizeEffect);
        break;
    }
    case Qt::Key_3:   //阴影效果
    {
        QGraphicsDropShadowEffect *dropShadowEffect = new QGraphicsDropShadowEffect;
        dropShadowEffect->setColor(QColor(63,63,63,100));
        dropShadowEffect->setBlurRadius(2);
        dropShadowEffect->setXOffset(10);
        setGraphicsEffect(dropShadowEffect);
        break;
    }
    case Qt::Key_4:   //透明效果
    {
        QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect;
        opacityEffect->setOpacity(0.4);
        setGraphicsEffect(opacityEffect);
        break;
    }
    case Qt::Key_5:   //取消图形项的图形效果
        graphicsEffect()->setEnabled(false);
        break;
    }
}

2.鼠标悬停效果:设置鼠标悬停在图形项上面时的光标外观和提示

//悬停事件处理,设置光标外观和提示
void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
    setCursor(Qt::OpenHandCursor);
    setToolTip(QString("我是%1号图形项").arg(m_id));
}

3.鼠标移动事件和右键菜单:实现用鼠标拖动图形项,并为图形项添加一个右键菜单

//鼠标移动事件处理,获得焦点并改变光标外观
void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    setFocus();
    setCursor(Qt::ClosedHandCursor);

    //鼠标拖动设置图形项的场景坐标
    //QPointF scenePos = mapToScene(event->pos());
    //setPos(scenePos);

    //直接用这一句顶上面两句
    QGraphicsItem::mouseMoveEvent(event);
}

//右键菜单事件处理,为图形项添加一个右键菜单
void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QMenu menu;
    QAction *viewAction = menu.addAction("移动到视图原点");
    QAction *sceneAction = menu.addAction("移动到场景原点");
    QAction *selectedAction = menu.exec(event->screenPos());
    if(selectedAction == viewAction)
    {
        setPos(-200,-150);   //与main函数中设置的场景矩形原点一致
    }
    else if(selectedAction == sceneAction)
    {
        setPos(0,0);
    }
}

4.动画
(1)使用QPropertyAnimation类来为图形项的某属性创建动画

int main(int argc,char *argv[])
{
	...
	//为图形项的rotation属性创建动画
    MyItem *item_111 = new MyItem;
    item_111->setId(111);
    item_111->setColor(Qt::yellow);
    item_111->setPos(15,50);
    scene.addItem(item_111);
    QPropertyAnimation *animation = new QPropertyAnimation(item_111,"rotation");
    animation->setDuration(2000);
    animation->setStartValue(0);
    animation->setEndValue(360);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    ...
}

(2)使用QGraphicsScene::advance()来推进场景

int main(int argc,char *argv[])
{
	...
	//创建定时器调用场景的advance()函数,并且会自动调用所有图形项的advance()函数
    QTimer timer;
    QObject::connect(&timer,&QTimer::timeout,&scene,&QGraphicsScene::advance);
    //timer.start(300);
    ...
}
    
//动画处理
void MyItem::advance(int phase)
{
    //第一个阶段不进行处理
    if(!phase)
    {
        return;
    }

    //图形项向不同方向随机移动
    int value = qrand() % 100;
    if(value < 25)
    {
        setRotation(45);
        moveBy(qrand() % 10,qrand() % 10);
    }
    else if(value < 50)
    {
        setRotation(-45);
        moveBy(-qrand() % 10,-qrand() % 10);
    }
    else if(value < 75)
    {
        setRotation(30);
        moveBy(-qrand() % 10,qrand() % 10);
    }
    else
    {
        setRotation(-30);
        moveBy(qrand() % 10,-qrand() % 10);
    }
}

5.碰撞检测
(1)重新实现使用QGraphicsItem::shape()函数来返回图形项准确的形状,结合碰撞判断函数使用
(2)重新实现collidesWithItem()函数来提供一个自定义的图形项碰撞算法

QGraphicsItem类中提供了下面这些碰撞判断函数:
collidesWithItem()来判断是否与指定的图形项进行了碰撞
collidesWithPath()来判断是否与指定的路径碰撞
collidingItems()来获取与该图形项碰撞的所有图形项的列表
这几个函数都有一个Qt::ItemSelectionMode参数来指定怎样进行图形项的选取,默认值是Qt::IntersectsItemShape
请添加图片描述

下面对第一种方式进行代码展示

//返回图形项对应的形状
QPainterPath MyItem::shape() const
{
    QPainterPath path;
    path.addRect(-10,-10,20,20);
    return path;
}

//执行实际的绘图操作
void MyItem::paint(QPainter *painter,const QStyleOptionGraphicsItem *,QWidget *)
{
    if(hasFocus() || !collidingItems().isEmpty())   //是否获得焦点或者有碰撞
    {
        painter->setPen(QPen(QColor(255,255,255,200)));
    }
    else
    {
        painter->setPen(QPen(QColor(100,100,100,100)));
    }
    painter->setBrush(m_brushColor);
    painter->drawRect(-10,-10,20,20);
}

6.图形项组:QGraphicsItemGroup图形项组为图形项提供了一个容器,下面代码对其使用进行了展示

int main(int argc,char *argv[])
{
	...
	//创建图形项组
    MyItem *item_10 = new MyItem;
    item_10->setId(10);
    item_10->setColor(Qt::blue);
    MyItem *item_11 = new MyItem;
    item_11->setId(11);
    item_11->setColor(Qt::green);
    QGraphicsItemGroup *group = new QGraphicsItemGroup;   //手动创建图形项组
    group->setFlag(QGraphicsItem::ItemIsMovable);
    group->addToGroup(item_10);   //将图形项添加到项组
    group->addToGroup(item_11);
    item_11->setPos(30,0);
    scene.addItem(group);   //将项组添加到场景
    //QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());   //使用场景对象直接创建图形项组
    //group->QGraphicsItemGroup::setHandlesChildEvents(false);   //让项组内的图形项可以捕获自己的相关事件
    //group->removeFromGroup(item1);   //从项组中删除图形项
    //scene.destroyItemGroup(group);   //销毁整个图形项组
    ...
}

(在QtCreator下的官方示例下有这个图形视图框架管理大量的图形项的示例:40000 Chips,可以作为参考)

7.打印:图形视图框架提供下面的渲染函数来完成打印功能
场景坐标上使用QGraphicsScene::render()函数实现打印
视图坐标上使用QGraphicsView::render()函数实现屏幕快照

int main(int argc,char *argv[])
{
	...
	//在打印机上进行打印
    QPrinter printer;
    if(QPrintDialog(&printer).exec() == QDialog::Accepted)
    {
        QPainter painter1(&printer);
        painter1.setRenderHint(QPainter::Antialiasing);
        scene.render(&painter1);
    }

    //实现屏幕快照功能,在项目生成的目录中保存图像
    QPixmap pixmap(400,300);
    QPainter painter2(&pixmap);
    painter2.setRenderHint(QPainter::Antialiasing);
    view.render(&painter2);
    painter2.end();
    pixmap.save("view.png");
	...
}

8.使用OpenGL进行渲染:使用QGraphicsView::setViewport()更改QGraphicsView的视口,就可以使用OpenGL进行渲染了

int main(int argc,char *argv[])
{
	...
	//自定义视图
    MyView view;
    view.setViewport(new QOpenGLWidget);
    //view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));   //使用OpenGL进行渲染
	...
}

(在QtCreator下的官方示例下有这个图形视图框架与OpenGL渲染的示例:Boxes,可以作为参考)

可以将我的示例中的pro文件内容修改为下面这样,来运行示例2,学习图形视图框架下相关的事件处理

#条件编译
#DEFINES += EXAMPLE_1
DEFINES += EXAMPLE_2

四、示例完整代码

1.MyScene.pro

QT += widgets
QT += printsupport
QT += opengl

SOURCES += \
    main.cpp \
    myitem.cpp \
    myview.cpp

HEADERS += \
    myitem.h \
    myview.h

#条件编译
#DEFINES += EXAMPLE_1
DEFINES += EXAMPLE_2

2.myitem.h

#ifndef MYITEM_H
#define MYITEM_H

#include <QGraphicsItem>
#include <QPainter>
#include <QMenu>
#include <QCursor>
#include <QKeyEvent>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneContextMenuEvent>
#include <QGraphicsEffect>
#include <QGraphicsObject>
#include <QPoint>
#include <QDebug>

class MyItem : public QGraphicsObject
{
public:
    MyItem(QGraphicsItem *parent = 0);

#if EXAMPLE_1
    QRectF boundingRect() const;
    void paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget);
#endif

#if EXAMPLE_2
    QRectF boundingRect() const;
    void paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget);
    void advance(int phase);
    QPainterPath shape() const;

    void setId(int id);
    void setColor(const QColor &color);

protected:
    void keyPressEvent(QKeyEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);

private:
    int m_id;
    QColor m_brushColor;
#endif
};
#endif // MYITEM_H

3.myitem.cpp

#include "myitem.h"

MyItem::MyItem(QGraphicsItem *parent) :
    QGraphicsObject(parent)
{
#if EXAMPLE_2
    m_brushColor = Qt::red;

    //开启图形项的特殊功能
    setFlag(QGraphicsItem::ItemIsFocusable);
    setFlag(QGraphicsItem::ItemIsMovable);
    setFlag(QGraphicsItem::ItemIsSelectable);
    setAcceptHoverEvents(true);   //使图形项支持悬停事件
#endif
}

#if EXAMPLE_1
//返回绘制图形项的矩形区域
QRectF MyItem::boundingRect() const
{
    qreal penWidth = 1;
    return QRectF(0 - penWidth/2,0 - penWidth/2,20 + penWidth,20 + penWidth);
}

//执行实际的绘图操作
void MyItem::paint(QPainter *painter,const QStyleOptionGraphicsItem *,QWidget *)
{
    painter->setBrush(Qt::red);
    painter->drawRect(0,0,20,20);
}
#endif

#if EXAMPLE_2
//返回绘制图形项的矩形区域
QRectF MyItem::boundingRect() const
{
    qreal adjust = 0.5;
    return QRectF(-10 - adjust,-10 - adjust,20 + adjust,20 + adjust);
}

//执行实际的绘图操作
void MyItem::paint(QPainter *painter,const QStyleOptionGraphicsItem *,QWidget *)
{
    if(hasFocus() || !collidingItems().isEmpty())   //是否获得焦点或者有碰撞
    {
        painter->setPen(QPen(QColor(255,255,255,200)));
    }
    else
    {
        painter->setPen(QPen(QColor(100,100,100,100)));
    }
    painter->setBrush(m_brushColor);
    painter->drawRect(-10,-10,20,20);
}

//动画处理
void MyItem::advance(int phase)
{
    //第一个阶段不进行处理
    if(!phase)
    {
        return;
    }

    //图形项向不同方向随机移动
    int value = qrand() % 100;
    if(value < 25)
    {
        setRotation(45);
        moveBy(qrand() % 10,qrand() % 10);
    }
    else if(value < 50)
    {
        setRotation(-45);
        moveBy(-qrand() % 10,-qrand() % 10);
    }
    else if(value < 75)
    {
        setRotation(30);
        moveBy(-qrand() % 10,qrand() % 10);
    }
    else
    {
        setRotation(-30);
        moveBy(qrand() % 10,-qrand() % 10);
    }
}

//返回图形项对应的形状
QPainterPath MyItem::shape() const
{
    QPainterPath path;
    path.addRect(-10,-10,20,20);
    return path;
}

//设置图形项序号
void MyItem::setId(int id)
{
    m_id = id;
}

//设置填充颜色
void MyItem::setColor(const QColor &color)
{
    m_brushColor = color;
}

//键盘按下事件处理,移动图形项
void MyItem::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    //移动图形项
    case Qt::Key_Up:   //上移
    {
        moveBy(0,-10);
        break;
    }
    case Qt::Key_Down:   //下移
    {
        moveBy(0,10);
        break;
    }
    case Qt::Key_Left:   //左移
    {
        moveBy(-10,0);
        break;
    }
    case Qt::Key_Right:   //右移
    {
        moveBy(10,0);
        break;
    }

    //添加图形效果
    case Qt::Key_1:   //模糊效果
    {
        QGraphicsBlurEffect *blurEffect = new QGraphicsBlurEffect;
        blurEffect->setBlurHints(QGraphicsBlurEffect::QualityHint);
        blurEffect->setBlurRadius(8);
        setGraphicsEffect(blurEffect);
        break;
    }
    case Qt::Key_2:   //染色效果
    {
        QGraphicsColorizeEffect *ColorizeEffect = new QGraphicsColorizeEffect;
        ColorizeEffect->setColor(Qt::white);
        ColorizeEffect->setStrength(0.6);
        setGraphicsEffect(ColorizeEffect);
        break;
    }
    case Qt::Key_3:   //阴影效果
    {
        QGraphicsDropShadowEffect *dropShadowEffect = new QGraphicsDropShadowEffect;
        dropShadowEffect->setColor(QColor(63,63,63,100));
        dropShadowEffect->setBlurRadius(2);
        dropShadowEffect->setXOffset(10);
        setGraphicsEffect(dropShadowEffect);
        break;
    }
    case Qt::Key_4:   //透明效果
    {
        QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect;
        opacityEffect->setOpacity(0.4);
        setGraphicsEffect(opacityEffect);
        break;
    }
    case Qt::Key_5:   //取消图形项的图形效果
        graphicsEffect()->setEnabled(false);
        break;
    }
}

//鼠标移动事件处理,获得焦点并改变光标外观
void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    setFocus();
    setCursor(Qt::ClosedHandCursor);

    //鼠标拖动设置图形项的场景坐标
    //QPointF scenePos = mapToScene(event->pos());
    //setPos(scenePos);

    //直接用这一句顶上面两句
    QGraphicsItem::mouseMoveEvent(event);
}

//悬停事件处理,设置光标外观和提示
void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
    setCursor(Qt::OpenHandCursor);
    setToolTip(QString("我是%1号图形项").arg(m_id));
}

//右键菜单事件处理,为图形项添加一个右键菜单
void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QMenu menu;
    QAction *viewAction = menu.addAction("移动到视图原点");
    QAction *sceneAction = menu.addAction("移动到场景原点");
    QAction *selectedAction = menu.exec(event->screenPos());
    if(selectedAction == viewAction)
    {
        setPos(-200,-150);   //与main函数中设置的场景矩形原点一致
    }
    else if(selectedAction == sceneAction)
    {
        setPos(0,0);
    }
}
#endif

4.myview.h

#ifndef MYVIEW_H
#define MYVIEW_H

#include <QGraphicsView>
#include <QGraphicsItem>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QDebug>

class MyView : public QGraphicsView
{
    Q_OBJECT

public:
    explicit MyView(QWidget *parent = 0);

protected:
#if EXAMPLE_1
    void mousePressEvent(QMouseEvent *event);
#endif

#if EXAMPLE_2
    void keyPressEvent(QKeyEvent *event);
#endif
};

#endif // MYVIEW_H

5.myview.cpp

#include "myview.h"

MyView::MyView(QWidget *parent) :
    QGraphicsView(parent)
{

}

#if EXAMPLE_1
void MyView::mousePressEvent(QMouseEvent *event)
{
    //视图坐标
    QPoint viewPos = event->pos();
    qDebug()<<"viewPos:"<<viewPos;

    //场景坐标
    QPointF scenePos = mapToScene(viewPos);
    qDebug()<<"scenePos:"<<scenePos;

    //图形项坐标
    QGraphicsItem *item = scene()->itemAt(scenePos,QTransform());
    if(item)
    {
        QPointF itemPos = item->mapFromScene(scenePos);
        qDebug()<<"itemPos:"<<itemPos;
    }
}
#endif

#if EXAMPLE_2
void MyView::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    case Qt::Key_Plus:
        scale(1.2,1.2);
        break;
    case Qt::Key_Minus:
        scale(1/1.2,1/1.2);
        break;
    case Qt::Key_Enter:
        rotate(30);
        break;
    }
    QGraphicsView::keyPressEvent(event);
}
#endif

6.main.cpp

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QPropertyAnimation>
#include <QTime>
#include <QTimer>
#include <QDialog>
#include <QPrinter>
#include <QPrintDialog>
#include <QPixmap>
#include <QPainter>
#include <QOpenGLWidget>
#include <qgl.h>
#include "myitem.h"
#include "myview.h"

#if EXAMPLE_1
//示例1:图形视图框架的结构和坐标系统
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);

    //场景
    QGraphicsScene scene;
    //scene.setSceneRect(0,0,400,300);   //设置场景矩形,指定视图显示的场景区域

    //自定义图形项
    MyItem *item = new MyItem;
    scene.addItem(item);
    item->setPos(10,10);   //设置坐标
    //item->setZValue(1);   //将item移动到rectItem之上

    //添加矩形图形项
    QGraphicsRectItem *rectItem = scene.addRect(QRect(0,0,100,100),QPen(Qt::blue),QBrush(Qt::green));
    rectItem->setPos(20,20);
    item->setParentItem(rectItem);   //将item作为rectItem子图形项,这样item默认显示在rectItem之上
    //rectItem->setRotation(30);   //设置旋转

    //自定义视图
    MyView view;
    view.setScene(&scene);
    view.setForegroundBrush(QColor(255,255,0,100));
    view.setBackgroundBrush(QPixmap("../myscene/background.jpg"));
    //view.setDragMode(QGraphicsView::ScrollHandDrag);   //设置鼠标为手掌形
    view.resize(400,300);
    view .show();

    return app.exec();
}
#endif

#if EXAMPLE_2
//示例2:图形视图框架的事件处理
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

    //场景
    QGraphicsScene scene;
    scene.setSceneRect(-200,-150,400,300);
    for(int i=0;i<5;i++)
    {
        //自定义图形项
        MyItem *item = new MyItem;
        item->setId(i+1);
        item->setColor(QColor(qrand() % 256,qrand() % 256,qrand() % 256));
        item->setPos(i*50 - 90,-50);
        scene.addItem(item);
    }

    //自定义视图
    MyView view;
    //view.setViewport(new QOpenGLWidget);
    //view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));   //使用OpenGL进行渲染
    view.setScene(&scene);
    view.setBackgroundBrush(QPixmap("../myscene/background.jpg"));
    view.setDragMode(QGraphicsView::RubberBandDrag);   //设置鼠标可以在视图上拖出橡皮筋框
    view.show();

    //为图形项的rotation属性创建动画
    MyItem *item_111 = new MyItem;
    item_111->setId(111);
    item_111->setColor(Qt::yellow);
    item_111->setPos(15,50);
    scene.addItem(item_111);
    QPropertyAnimation *animation = new QPropertyAnimation(item_111,"rotation");
    animation->setDuration(2000);
    animation->setStartValue(0);
    animation->setEndValue(360);
    animation->start(QAbstractAnimation::DeleteWhenStopped);

    //创建定时器调用场景的advance()函数,并且会自动调用所有图形项的advance()函数
    QTimer timer;
    QObject::connect(&timer,&QTimer::timeout,&scene,&QGraphicsScene::advance);
    //timer.start(300);

    //创建图形项组
    MyItem *item_10 = new MyItem;
    item_10->setId(10);
    item_10->setColor(Qt::blue);
    MyItem *item_11 = new MyItem;
    item_11->setId(11);
    item_11->setColor(Qt::green);
    QGraphicsItemGroup *group = new QGraphicsItemGroup;   //手动创建图形项组
    group->setFlag(QGraphicsItem::ItemIsMovable);
    group->addToGroup(item_10);   //将图形项添加到项组
    group->addToGroup(item_11);
    item_11->setPos(30,0);
    scene.addItem(group);   //将项组添加到场景
    //QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());   //使用场景对象直接创建图形项组
    //group->QGraphicsItemGroup::setHandlesChildEvents(false);   //让项组内的图形项可以捕获自己的相关事件
    //group->removeFromGroup(item1);   //从项组中删除图形项
    //scene.destroyItemGroup(group);   //销毁整个图形项组

    //在打印机上进行打印
    //QPrinter printer;
    //if(QPrintDialog(&printer).exec() == QDialog::Accepted)
    //{
    //    QPainter painter1(&printer);
    //    painter1.setRenderHint(QPainter::Antialiasing);
    //    scene.render(&painter1);
    //}

    //实现屏幕快照功能,在项目生成的目录中保存图像
    QPixmap pixmap(400,300);
    QPainter painter2(&pixmap);
    painter2.setRenderHint(QPainter::Antialiasing);
    view.render(&painter2);
    painter2.end();
    pixmap.save("view.png");

    return app.exec();
}
#endif

/*
*QtCreator下的演示示例
*图形视图框架管理大量的图形项:40000 Chips
*图形视图框架与OpenGL渲染:Boxes
*/

五、QtCreator官方示例

图形视图框架管理大量的图形项:40000 Chips
请添加图片描述

图形视图框架与OpenGL渲染:Boxes
请添加图片描述


总结

通过以上的学习,对于这个由场景、视图和图形项这三大类组成的图形视图框架有了更加清晰的认识。文中提到的QtCreator下的官方示例我也运行查看了下,作为参考也可以学习本文示例外的一些知识,推荐大家也去看看


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

学习书籍:【Qt Creator快速入门_霍亚飞编著】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1172980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于match_phrase搜索的分词优化

ES 的match_phrase 搜索需要完整匹配输入的内容&#xff0c;比如我们搜索 ‘中国人民’ &#xff0c;要保证的是doc中必须有 ‘中国人民’ 的内容出现。再比如我们搜索 ‘国人民’ 时&#xff0c;结果集中的 doc 中就要有 ‘国人民’ 的内容。一般在使用match 或 term 搜索的时…

DL Homework 6

目录 一、概念 &#xff08;1&#xff09;卷积 &#xff08;2&#xff09;卷积核 &#xff08;3&#xff09;特征图 &#xff08;4&#xff09;特征选择 &#xff08;5&#xff09;步长 &#xff08;6&#xff09;填充 &#xff08;7&#xff09;感受野 二、探究不同卷…

植物花粉深度学习图片数据集大合集

最近收集了一波有关于植物花粉的图片数据集&#xff0c;可以用于相关深度学习模型的搭建&#xff0c;废话不多说&#xff0c;上数据集&#xff01;&#xff01;&#xff01; 1、23种花粉类型805张花粉图像数据集 关于此数据&#xff1a;花粉种类和类型的分类是法医抱粉学、考…

2023年中国金融控股公司研究报告

第一章 行业概况 1.1 定义 金融控股公司这一术语最初源自美国&#xff0c;特别是在美国的《金融服务法案》关于银行控股公司组织结构的条文中&#xff0c;首次出现了“金融控股公司”&#xff08;Financial Holding Company&#xff09;这一法律术语&#xff0c;尽管法案中并…

2023年【高压电工】报名考试及高压电工最新解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 高压电工报名考试考前必练&#xff01;安全生产模拟考试一点通每个月更新高压电工最新解析题目及答案&#xff01;多做几遍&#xff0c;其实通过高压电工作业考试题库很简单。 1、【单选题】 ()是指继电器不动作时处于…

Windows 内置Linux子系统的配置(From WSL1 to WSL2)

目录 我是如何从WSL1转到WSL2的? WSL1与WSL2的功能区别: 配置下载源 SSH配置 优雅使用windows的Linux子系统 我是如何从WSL1转到WSL2的? 第一次安装的子系统是WSL1的&#xff0c;因为不能使用systemctl &#xff0c;以及因为WSL1没有完整的Linux内核,所以使得WSL1很多命令…

vivado查看报告和消息1

AMD Vivado ™ 集成设计环境 (IDE) 可生成报告和消息 &#xff0c; 以便告知您各种工具交互期间的设计或设计进程状态。报告由 您&#xff08; 或工具 &#xff09; 在执行设计流程中的任意关键步骤时生成。报告可汇总有关设计的具体信息。 本工具可在设计进程中每个步骤自动…

软通杯算法竞赛--周赛题目(一)

目录 一、S属性大爆发 二、日期杯 三、 三人行必由我师 四、集合之差 五、咱们计算机不懂烷烃 六、适度跑步健康长寿 一、S属性大爆发 测试用例 5 esS qwert codeforces PoSgju LkkJKkO 输出案例 二、日期杯 输入案例&#xff1a; 3 2022 2022 11 1900 2100 15 1989 20…

EtherCAT主站写从站EEPROM抓包分析

0 工具准备 1.EtherCAT主站 2.EtherCAT从站&#xff08;本文使用步进电机驱动器&#xff09; 3.Wireshark1 抓包分析 1.1 报文总览 本文主站设置从站1字地址为0的EEPROM数据为0x3C00&#xff08;设置完毕后请还原字0的EEPROM数据&#xff09;&#xff0c;使用Wireshark抓取到…

检索已删除的视频方法,12 个最佳 Android 视频恢复应用程序/软件

您可能倾向于定期从 Android 设备中删除不必要的视频&#xff0c;同时保留精美的视频以使其保持井井有条。然而&#xff0c;有些人在删除一些有价值的视频而不是无用的视频时无意中犯了错误。如果您错误地从移动设备中删除了视频或清除了其内存&#xff0c;您可能想知道是否有办…

某大厂伺服驱动器量产方案

本文介一款大厂量产伺服驱动器方案&#xff01;带2500线省线式编码器&#xff0c;17位增量编码器&#xff0c;20位绝对值编码器&#xff01;标配CANopen、高精度运动控制&#xff0c;高速总线通讯&#xff0c;主芯片28335FPGA&#xff0c;已验证过&#xff0c;带can和485通讯&a…

OSError: libomp.so: cannot open shared object file: No such file or directory

报错&#xff1a;OSError: libomp.so: cannot open shared object file: No such file or directory https://stackoverflow.com/questions/52401840/what-is-the-ctypes-cdll-default-path 没有libomp.so 总算找到啦&#xff01;链接 export LD_LIBRARY_PATH/usr/lib/llvm…

【java学习—十二】文件字符流(3)

文章目录 1. 文件字符输入流2. 文件字符输出流3. 字符流完成拷贝文件 1. 文件字符输入流 读取文件操作步骤 : &#xff08;1&#xff09;建立一个流对象&#xff0c;将已存在的一个文件加载进流。 FileReader fr new FileReader(“Test.txt”);&#xff08;2&#xff09;创建…

C站你好,和你相遇的第1825天

文章目录 机缘收获日常成就憧憬 机缘 ①. 你好,C站 ②. 初识JAVA编程,遇到问题,粘贴问题百度搜索,大都数出来的解决方案都能在C站得到解决,对C站有一定的好感 ③. 起初在CSDN写博客,主要用来记录日常学习过程中的笔记、不断调整自己的笔记,如JAVA基础、框架、虚拟机等,为后…

【Linux】搭建Linux环境等——小喵爱上了林利克斯1

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;大大会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

Elasticsearch:使用你的 RAG 来进行聊天

什么是人工智能中的检索增强生成&#xff08;RAG&#xff09;&#xff1f; 检索增强生成 (RAG)&#xff0c;与你的文档聊天的超级英雄&#xff0c;架起信息检索和文本生成世界的桥梁&#xff01; 这就像福尔摩斯和莎士比亚联手解决需要大量知识的复杂任务。 RAG 突然介入&…

分享96个工作总结PPT,总有一款适合您

分享96个工作总结PPT&#xff0c;总有一款适合您 工作总结PPT下载链接&#xff1a;https://pan.baidu.com/s/18AriuVGxwINHrmgndX74dw?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

【数智化案例展】新余钢铁集团——华院智能配煤解决方案

‍ 华院计算案例 本项目案例由华院计算投递并参与数据猿与上海大数据联盟联合推出的《2023中国数智化转型升级创新服务企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 华院智能制造基于对工业生产场景的深入理解&#xff0c;秉承算法和应用场景相结合…

2023年金融科技建模大赛(初赛)开箱点评

各位同学大家好&#xff0c;我是Toby老师。2023年金融科技建模大赛&#xff08;初赛&#xff09;从今年10月14日开始&#xff0c;11月11日结束。 比赛背景 发展数字经济是“十四五”时期的重大战略规划。2023年&#xff0c;中共中央、国务院印发了《数字中国建设整体布局规划》…

速学数据结构 | 用队列实现栈你都被难住了?那是你没掌握好技巧

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525;个人专栏:《Linux深造日志》《C干货基地》 ⛺️生活的理想&#xff0c;就是为了理想的生活! &#x1f4cb; 前言 &#x1f308;hello&#xff01; 各位铁铁们大家好啊&#xff0c;栈和队列我们都学过了那么试试用队列实…