《十四》QT Graphics View图形视图框架

一、Graphics View框架结构的主要特点

Graphics View框架结构的主要特点如下:
(1) 在Graphics View框架结构中,系统可以利用Qt绘图系统的反锯齿、OpenGL工具来改善绘图性能。
(2) Graphics View支持事件传播体系结构,可以使图元场景(scene)中的交互能力提高1倍,图元能够处理键盘事件和鼠标事件。其中,鼠标事件包括鼠标被按下、移动、释放和双击,还可以跟踪鼠标的移动。
(3) 在Graphics View框架中,通过二元空间划分树(Binary Space Partitioning,BSP)提供快速的图元查找,这样就能够实时地显示包含上百万个图元的大场景。

二、Graphics View框架结构的三元素

Graphics View框架结构主要包含了场景类(QGraphicsScene)、视图类(QGraphicsView)和图元类(QGraphicsItem)。场景类提供了一个用于管理位于其中的众多图元容器,视图类用于显示场景中的图元,一个场景可以通过多个视图表现,一个场景包括多个几何图形。它们三者之间的关系可用图表示:

 1、场景类:QGraphicsScene类

它是一个用于放置图元的容器,本身是不可见的,必须通过与之相连的视图类来显示及与外界进行交互操作。

场景类主要完成的工作包括提供对它包含的图元的操作接口和传递事件、管理各个图元的状态(如选择和焦点处理)、提供无变换的绘制功能(如打印)等。

事件传播体系结构将场景事件发送给图元,同时也管理图元之间的事件传播。如果场景接收了在某一点的鼠标单击事件,场景会将事件传给这一点的图元。

 2、视图类: QGraphicsView 类

它提供一个可视的窗口,用于显示场景中的图元。在同一个场景中可以有多个视图,也可以为相同的数据集提供几种不同的视图。视图接收键盘和鼠标的输入事件,并将它们翻译为场景事件(将坐标转换为场景的坐标)。

3、图元类(QGraphicsItem) 

它是场景中各个图元的基类,在它的基础上可以继承出各种图元类,Qt已经预置的包括直线(QGraphicsLineItem)、椭圆(QGraphicsEllipseItem)、文本图元(QGraphicsTextItem)、矩形(QGraphicsRectItem)等。当然,也可以在QGraphicsItem类的基础上实现自定义的图元类,即用户可以继承QGraphicsItem实现符合自己需要的图元。

QGraphicsItem主要支持如下功能:

  • 鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件。
  • 处理键盘输入事件。
  • 拖 处理拖曳事件。
  • 碰撞检测。

此外,图元有自己的坐标系统,也提供场景和图元。图元还可以通过QGraphicsItem::matrix( )函数来进行自身的交换,可以包含子图元。 

三、Graphics Viewk框架结构的坐标系统

Graphics View 坐标基于笛卡儿坐标系,一个图元的场景具有x坐标和y坐标。当使用没有变换的视图观察场景时,场景中的一个单元对应屏幕上的一个像素。

三个Graphics View 基本类有各自不同的坐标系,场景坐标、视图坐标和图元坐标。Graphics View提供了三个坐标系统之间的转换函数。在绘制图形时,GraphicsView 的场景坐标对应QPainter的逻辑坐标、视图坐标和设备坐标。

1.场景坐标 

场景坐标是所有图元的基础坐标系统。场景坐标系统描述了项层的图元,每个图元都有场景坐标和相应的包容框。场景坐标的原点在场景中心,坐标原点是x轴正方向向右,y轴正方向向下。

QGraphicsScene类的坐标系以中心为原点(0,0), 如下图所示。

 

2.视图坐标

视图坐标是窗口部件的坐标。视图坐标的单位是像素。QGraphicsView视口的左上角是(0,0),X轴正方向向右,Y轴正方向向下。所有的鼠标事件最开始都是使用视图坐标。

QGraphicsView类继承自QWidget类,因此它和其他的QWidget类一样以窗口的左上角作为自己坐标系的原点,如下图所示。

 

3、图元坐标

图元使用自己的本地坐标,这个坐标系统通常以图元中心为原点,这也是所有变换的原点。图元坐标方向是X轴正方向向右,Y轴正方向向下。创建图元后,只需要注意图元坐标就可以了,QGraphicsScene和QGraphicsView会完成所有的变换。

QGraphicsItem类的坐标系,在调用QGraphicsItem类的paint()函数重画图元时则以此坐标系为基准,如下图所示。

 

根据需要,Qt提供了这三个坐标系之间的互相转换函数,以及图元与图元之间的转换函数,若需从QGraphicstem坐标系中的某点坐标转换到场景中的坐标,则可调用QGraphicstem 的mapToScene( )函数进行映射。而GraphicsItem的mapToParent()函数则可将QGraphicsItem 坐标
系中的某点坐标映射至它的上一级坐标系中,有可能是场景坐标,也有可能是另一个QGraphicsItem坐标。

 Graphics View框架提供了多种变换函数,如下所示:

 图形视图实例

设计界面,将图片进行翻转,倾斜,缩放操作。

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QGraphicsView>//视图
#include<QGraphicsScene>//场景
#include<QFrame>
#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QGroupBox>
#include<QSlider>

#include"pixitem.h"
#include<math.h>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public:
    void CreateControlFrameFunc();//创建控件框架

private:
    int iAngle;
    qreal scalevalues;//缩放
    qreal leanvalues;//倾斜

    QGraphicsView *view;
    QFrame *controlframe;
    Pixitem *pixitem;

private slots:
    void rotateFunc(int);//旋转
    void scaleFunc(int);//缩放
    void leanFunc(int);//倾斜
};
#endif // WIDGET_H

 添加新项目,选择c++类

 pixitem.h

#ifndef PIXITEM_H
#define PIXITEM_H

#include<QGraphicsItem>//图元类
#include<QPixmap>
#include<QPainter>

class Pixitem : public QGraphicsItem
{
public:
    Pixitem(QPixmap *pixmap);

private:
    QPixmap pix;

public:
    //此函数只刷新固定区域
    QRectF boundingRect() const;
    //绘制操作
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );

};

#endif // PIXITEM_H

pixitem.cpp

#include "pixitem.h"

Pixitem::Pixitem(QPixmap *pixmap)
{
    pix=*pixmap;
}

QRectF Pixitem::boundingRect() const
{
    return QRectF(-2-pix.width()/2,-2-pix.height()/2,pix.width()+4,pix.height()+4);
}

void Pixitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawPixmap(-pix.width()/2,-pix.height()/2,pix);
}

这段代码是一个基于Qt框架的图形项类,它继承自QGraphicsItem类。这个类可以用来在Qt的图形场景中绘制一个图像。在构造函数中,传入了一个QPixmap对象的指针,将其保存在类成员变量pix中。

在boundingRect函数中,返回了该图像的矩形边界。

在paint函数中,将该图像绘制到场景中心。

widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle("图形视图框架测试");
    iAngle=0;
    scalevalues=2;
    leanvalues=2;

    //场景
    QGraphicsScene *sence=new QGraphicsScene;
    sence->setSceneRect(-200,-200,380,380);

    //此图片自己根据名称,自己加入
    QPixmap *pixmap=new QPixmap(":/niubi/caeba5a347c20618-9f007285b539607f-c9a19252f2427635495882e3c36195f3.jpg");

    pixitem=new Pixitem(pixmap);
    sence->addItem(pixitem);//将图片添加到场景
    pixitem->setPos(0,0);

    //视图
    view=new QGraphicsView;
    view->setScene(sence);
    view->setMinimumSize(800,600);

    controlframe=new QFrame;
    CreateControlFrameFunc();



    //主窗体布局设计
    QHBoxLayout *hlayout=new QHBoxLayout;
    hlayout->addWidget(view);
    hlayout->addWidget(controlframe);

    setLayout(hlayout);//向布局中添加子布局



}

Widget::~Widget()
{
}
void Widget::CreateControlFrameFunc()
{
    //旋转
    QSlider *rotateslilder=new QSlider;
    rotateslilder->setOrientation(Qt::Horizontal);
    rotateslilder->setRange(0,360);

    QHBoxLayout *rotatelayout=new QHBoxLayout;
    rotatelayout->addWidget(rotateslilder);

    QGroupBox *rotategroup=new QGroupBox("图形旋转");
    rotategroup->setLayout(rotatelayout);

    //缩放
    QSlider *scaleslilder=new QSlider;
    scaleslilder->setOrientation(Qt::Horizontal);
    scaleslilder->setRange(0,2*scalevalues);
    scaleslilder->setValue(scalevalues);

    QHBoxLayout *scalelayout=new QHBoxLayout;
    scalelayout->addWidget(scaleslilder);

    QGroupBox *scalegroup=new QGroupBox("图形缩放");
    scalegroup->setLayout(scalelayout);

    //倾斜
    QSlider *leanslilder=new QSlider;
    leanslilder->setOrientation(Qt::Horizontal);
    leanslilder->setRange(0,2*leanvalues);
    leanslilder->setValue(leanvalues);

    QHBoxLayout *leanlayout=new QHBoxLayout;
    leanlayout->addWidget(leanslilder);

    QGroupBox *leangroup=new QGroupBox("图形倾斜");
    leangroup->setLayout(leanlayout);

     connect(rotateslilder,SIGNAL(valueChanged(int)),this,SLOT(rotateFunc(int)));
     connect(leanslilder,SIGNAL(valueChanged(int)),this,SLOT(leanFunc(int)));
     connect(scaleslilder,SIGNAL(valueChanged(int)),this,SLOT(scaleFunc(int)));

    //右边部分设计布局
    QVBoxLayout *vlayoutframe=new QVBoxLayout;
    vlayoutframe->addWidget(rotategroup);
    vlayoutframe->addWidget(scalegroup);
    vlayoutframe->addWidget(leangroup);

    controlframe->setLayout(vlayoutframe);
}

上面是对布局进行处理,以及槽函数链接,

void Widget::rotateFunc(int val)
{
    view->rotate(val-iAngle);
    iAngle=val;

}

void Widget::scaleFunc(int val)
{
    qreal qs;
    if(val>scalevalues){
        qs=pow(1.1,(val-scalevalues));
    }else{
        qs=pow(1/1.1,(scalevalues-val));
    }
    view->scale(qs,qs);
    scalevalues=val;
}

void Widget::leanFunc(int val)
{
    view->shear((val-leanvalues)/2.0,0);
    leanvalues=val;
}

这是三个成员函数,属于一个名为Widget的类。这个类包含了一个名为view的成员变量,该变量可能是一个指向某种视图对象的指针。

这三个函数分别实现了旋转、缩放和倾斜这三个操作。

其中,rotateFunc(int val)函数通过调用view对象的rotate()函数来实现旋转操作;

scaleFunc(int val)函数通过调用view对象的scale()函数来实现缩放操作;

leanFunc(int val)函数通过调用view对象的shear()函数来实现倾斜操作。这些函数都接受一个整数参数val,用来指定需要执行的旋转、缩放或倾斜操作的程度。

在执行这些操作时,会用类的成员变量iAngle、scalevalues和leanvalues来记录上一次执行操作时的程度,从而计算出需要执行的实际程度。

实际效果:

感谢阅读!!!!!!!!!

  • 32
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是关于Qt Graphics View的教程: 1. 官方文档:Qt Graphics View官方文档是使用该框架的最佳参考资料,其中详细介绍了该框架的所有功能和API。 2. 基本概念:在学习Qt Graphics View之前,需要先了解一些基本概念,如场景(Scene)、视图View)、图元(Item)等。 3. 创建场景和视图:使用Qt Graphics View创建场景和视图非常简单。可以通过代码或Qt Designer创建一个新的Graphics View窗口。首先需要创建场景,然后将场景与视图关联。 4. 添加图元:可以使用Qt Graphics View中的图元(Item)来绘制2D图形。可以添加图元到场景中,然后它们就会显示在视图中。Qt Graphics View提供了一些内置的图元类,如矩形、椭圆、文字、线条等。 5. 图元转换和变换:使用Qt Graphics View可以对图元进行多种转换和变换操作,如平移、缩放、旋转、剪切、选择等。这些操作可以通过使用QTransform类来实现。 6. 事件处理和信号机制:Qt Graphics View提供了丰富的事件和信号机制,方便用户进行图形交互和动画效果的实现。可以通过重载事件处理函数和连接信号和槽函数来处理这些事件和信号。 7. 动画效果:使用Qt Graphics View可以实现各种动画效果,如平移、旋转、缩放等。可以使用QPropertyAnimation类来实现这些效果。 8. 场景和视图的组合:使用Qt Graphics View可以将多个场景和视图组合在一起,创建复杂的图形场景。可以使用QGraphicsProxyWidget类将QWidget转换为图元,然后将它们添加到场景中。 希望以上教程能帮助你了解Qt Graphics View

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值