QGraphics类型学习使用【Qt】【C++】

QGraphics类型学习使用

首先已知,QGraphicsView,QGraphicsScene, QGraphicsItem,分别称为:视图,场景,图元,图表就是各种各样的元素,图片元素,线条元素,等等,场景就是容纳图元的一个容器,场景不会显示出来,这句话很关键。若是想将其显示到屏幕上,需要将场景设置到视图中,由视图负责显示。

需求

利用QGraphics家族类成员实现将图片显示出来,并对图片进行旋转,伸缩等操作。

以下是完成后的结果图:

过程

首先创建了项目,并将图片添加进qrc资源文件(不添加也行,不影响):

代码如下:

c 复制代码
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QPixmap *pm = new QPixmap("://earth.jpg");
    QGraphicsView *view = new QGraphicsView(this);
    QGraphicsScene *scene = new QGraphicsScene;

    QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem(*pm);
    setGeometry({300,300, 800, 600});
    view->resize(pixmap->pixmap().width(),pixmap->pixmap().height());
    scene->addItem(pixmap);
    view->setScene(scene);

    QVBoxLayout *vLayout = new QVBoxLayout;
    QSlider *s1 = new QSlider(Qt::Horizontal);
    QSlider *s2 = new QSlider(Qt::Horizontal);


    vLayout->addWidget(s1);
    vLayout->addWidget(s2);


    QHBoxLayout *hLayout = new QHBoxLayout(this);
    hLayout->addWidget(view);
    hLayout->addLayout(vLayout);
}

Widget::~Widget()
{
}

可以看到只显示的图片的一部分,根据下面和右边的滚动条知道可以通过滑动来展示图片,

溯源可知,由于QGraphicsView继承自QAbstractScrollArea,顾名思义,它的父类具有滚动功能,具体不深究,知道是因为那个部分带来的滚动条即可。

但是我们的目的是显示所有图片的细节,可以放大图片:

c 复制代码
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QPixmap *pm = new QPixmap("://earth.jpg");

    QPixmap newPm = pm->scaled(pm->width() / 1.5, pm->height() / 1.5);
    QGraphicsView *view = new QGraphicsView(this);
    QGraphicsScene *scene = new QGraphicsScene;

    QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem(newPm);
    setGeometry({500,500, pixmap->pixmap().width()+100,pixmap->pixmap().height()});
    view->resize(pixmap->pixmap().width(),pixmap->pixmap().height()- 100);
    scene->addItem(pixmap);
    view->setScene(scene);

    QVBoxLayout *vLayout = new QVBoxLayout;
    QSlider *s1 = new QSlider(Qt::Horizontal);
    QSlider *s2 = new QSlider(Qt::Horizontal);


    vLayout->addWidget(s1);
    vLayout->addWidget(s2);


    QHBoxLayout *hLayout = new QHBoxLayout(this);
    hLayout->addWidget(view);
    hLayout->addLayout(vLayout);
}

Widget::~Widget()
{
}

得到:

将右侧滚动条大小进行调整,整体大小进行调整:

c 复制代码
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QPixmap *pm = new QPixmap("://earth.jpg");

    QPixmap newPm = pm->scaled(pm->width() / 1.5, pm->height() / 1.5);
    QGraphicsView *view = new QGraphicsView;
    QGraphicsScene *scene = new QGraphicsScene;

    QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem(newPm);
    setGeometry({500,500, pixmap->pixmap().width()+100,pixmap->pixmap().height()});
    view->resize(pixmap->pixmap().width(),pixmap->pixmap().height()- 100);
    scene->addItem(pixmap);
    view->setScene(scene);

    QVBoxLayout *vLayout = new QVBoxLayout;
    QSlider *s1 = new QSlider(Qt::Horizontal);
    QSlider *s2 = new QSlider(Qt::Horizontal);
    QHBoxLayout *gbox1 = new QHBoxLayout;
    QHBoxLayout *gbox2 = new QHBoxLayout;
    QLabel *label1 = new QLabel("旋转:");
    QLabel *label2 = new QLabel("伸缩:");
    gbox1->addWidget(label1);
    gbox1->addWidget(s1);
    gbox2->addWidget(label2);
    gbox2->addWidget(s2);

    vLayout->addLayout(gbox1);
    vLayout->addLayout(gbox2);


    QHBoxLayout *hLayout = new QHBoxLayout(this);
    hLayout->addWidget(view);
    hLayout->addLayout(vLayout);
}

Widget::~Widget()
{
}

接下来就可以设置旋转和缩放的槽函数了,两种方式:

  • 旋转视图:
c 复制代码
void Widget::rotate(int value)
{
    view->rotate(value);
    update();
}
  • 旋转图元:
c 复制代码
void Widget::rotate(int value)
{
    pixmap->setRotation(value);

    update();
}

此时发现问题:旋转中心点是左上角:

这是因为,在两种旋转函数中:

  • rotate: 旋转原点是以中心点为基准进行旋转的。
  • setRotation: 旋转原点是以左上角为基准进行旋转的。

所以需要修改旋转原点:

setTransformOriginPoint:这个函数通常用于设置QGraphicItem及其子类的变换中心点,可作为旋转,伸缩时的中心点。

所以:

c 复制代码
void Widget::rotate(int value)
{
    pixmap->setTransformOriginPoint(pixmap->pixmap().width()/2, pixmap->pixmap().height()/2);
    pixmap->setRotation(value);

    update();
}

发现旋转没有一圈,设置一下滚动条的范围即可:s1->setRange(0,360);

接下来实现伸缩:

c 复制代码
void Widget::scale(int value)
{
    pixmap->setTransformationMode(Qt::SmoothTransformation);
    pixmap->setScale(value);
    update();
}

运行后:

发现伸缩大小比例不对,将滚动条的范围设置为一个合适的范围:
s2->setRange(0,2);,设置后运行:

发现slider的步长太大,但是我们需要的是0.1级别的调整,查询发现slider

设置步长的函数为setSingleStep(int),只能设置最小为1的步长,因此我们重新调整,将范围设置为:s2->setRange(0,20);

c 复制代码
void Widget::scale(int value)
{

    pixmap->setTransformationMode(Qt::SmoothTransformation);
    pixmap->setScale(value*1.0/10);
    update();
}

运行后发现;

第1点是期望伸缩中心点是在图片的中心点,但是实际上是在图片左上角进行伸缩的,所以需要修该一下:pixmap->setTransformOriginPoint(pixmap->pixmap().width()/2, pixmap->pixmap().height()/2);

其实也就是将

rotate函数里面的这个setTransformOriginPoint放到构造函数中。

第2点就是伸缩的时候是从slider的值改变的第一个量伸缩的,我们期待的是从当前值进行伸缩,接下来进行修改:

因为涉及到缩小和放大,我们可以将slider的初始值设置为10,进过变换也就是1,即没有伸缩过的图片:
s2->setValue(10);

slider位于中间,向左缩小,向右放大:


自此代码简单完成。是自己学习路上的过程笔记,知识浅薄,或许不具备学习来使用。

全部完整代码

c 复制代码
// widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QPixmap>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSlider>
#include <QGroupBox>
#include <QLabel>
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
   QGraphicsView *view;
   QGraphicsPixmapItem *pixmap;
   QGraphicsScene *scene;

private slots:
    void rotate(int);
    void scale(int);

};
#endif // WIDGET_H
c 复制代码
// widget.cpp
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QPixmap *pm = new QPixmap("://earth.jpg");

    QPixmap newPm = pm->scaled(pm->width() / 1.5, pm->height() / 1.5);
    view = new QGraphicsView;
    scene = new QGraphicsScene;

    pixmap = new QGraphicsPixmapItem(newPm);
    setGeometry({500,500, pixmap->pixmap().width()+100,pixmap->pixmap().height()});
    view->resize(pixmap->pixmap().width(),pixmap->pixmap().height()- 100);
    scene->addItem(pixmap);
    view->setScene(scene);

    QVBoxLayout *vLayout = new QVBoxLayout;
    QSlider *s1 = new QSlider(Qt::Horizontal);
    s1->setRange(0,360);
    QSlider *s2    = new QSlider(Qt::Horizontal);
    s2->setRange(0,20);
    s2->setValue(10);
    QHBoxLayout *gbox1 = new QHBoxLayout;
    QHBoxLayout *gbox2 = new QHBoxLayout;
    QLabel *label1 = new QLabel("旋转:");
    QLabel *label2 = new QLabel("伸缩:");
    gbox1->addWidget(label1);
    gbox1->addWidget(s1);
    gbox2->addWidget(label2);
    gbox2->addWidget(s2);

    vLayout->addLayout(gbox1);
    vLayout->addLayout(gbox2);


    QHBoxLayout *hLayout = new QHBoxLayout(this);
    hLayout->addWidget(view);
    hLayout->addLayout(vLayout);

    pixmap->setTransformOriginPoint(pixmap->pixmap().width()/2, pixmap->pixmap().height()/2);
    connect(s1, SIGNAL(valueChanged(int)), this, SLOT(rotate(int)));
    connect(s2, SIGNAL(valueChanged(int)), this, SLOT(scale(int)));
}

Widget::~Widget()
{
}

void Widget::rotate(int value)
{
    pixmap->setTransformOriginPoint(pixmap->pixmap().width()/2, pixmap->pixmap().height()/2);
    pixmap->setRotation(value);

    update();
}

void Widget::scale(int value)
{
    pixmap->setTransformationMode(Qt::SmoothTransformation);
    pixmap->setScale(value*1.0/10);
    update();
}

新人创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看。

相关推荐
流浪的小新1 分钟前
【AI】人工智能、LLM学习资源汇总
人工智能·学习
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人1 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
机器视觉知识推荐、就业指导1 小时前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
忘梓.2 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
Evand J2 小时前
LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度
开发语言·matlab
LucianaiB2 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python
Ronin3052 小时前
11.vector的介绍及模拟实现
开发语言·c++