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

QGraphics类型学习使用

  • 需求
  • 过程
  • 全部完整代码

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

需求

  利用QGraphics家族类成员实现将图片显示出来,并对图片进行旋转,伸缩等操作。
以下是完成后的结果图:

过程

  首先创建了项目,并将图片添加进qrc资源文件(不添加也行,不影响):
在这里插入图片描述
  代码如下:

#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,顾名思义,它的父类具有滚动功能,具体不深究,知道是因为那个部分带来的滚动条即可。
  但是我们的目的是显示所有图片的细节,可以放大图片:

#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()
{
}


得到:
在这里插入图片描述

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

#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()
{
}


在这里插入图片描述
  接下来就可以设置旋转和缩放的槽函数了,两种方式:

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

    update();
}

此时发现问题:旋转中心点是左上角:
在这里插入图片描述

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

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

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

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

    update();
}

在这里插入图片描述
发现旋转没有一圈,设置一下滚动条的范围即可:s1->setRange(0,360);

接下来实现伸缩:

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);

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位于中间,向左缩小,向右放大:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  自此代码简单完成。是自己学习路上的过程笔记,知识浅薄,或许不具备学习来使用。

全部完整代码

// 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

// 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();
}


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity Apple Vision Pro 开发:Metal 渲染模式开启透视遇到背景黑屏的解决方法

XR 开发者社区链接&#xff1a; SpatialXR社区&#xff1a;完整课程、项目下载、项目孵化宣发、答疑、投融资、专属圈子 以下步骤适用于 PolySpatial 2.0 及以上的版本。 我们可以在 Project Settings 中的 Apple visionOS 里将 App Mode 设为 Metal Rendering with Composit…

【C语言】分支结构switch

switch分支语句 多适用于明确表达式结果的情况&#xff0c;多个分支&#xff0c;用if过于繁琐。 case后跟具体的表达式值&#xff0c;break&#xff1b;跳出分支语句。 #include <stdio.h> #include <math.h> /* 功能&#xff1a;选择结构&#xff08;switch&…

Flink CDC同步mysql数据到doris

前置参考 flink快速安装&#xff1a;Flink入门-CSDN博客 doris快速安装&#xff1a;Apache Doris快速安装-CSDN博客 Flink CDC简介 Flink CDC 是一个基于流的数据集成工具&#xff0c;旨在为用户提供一套功能更加全面的编程接口&#xff08;API&#xff09;。 该工具使得用户能…

AI测试之 TestGPT

如今最火热的技术莫非OpenAI的ChatGPT莫属&#xff0c;AI技术也在很多方面得到广泛应用。今天我们要介绍的TestGPT就是一个软件测试领域中当红的应用。 TestGPT是什么&#xff1f; TestGPT是一家总部位于以色列特拉维夫的初创公司 CodiumAI Ltd.&#xff0c;发布的一款用于测…

hadoop集群搭建-克隆虚拟机,安装jdk,hadoop

2.2 hadoop运行环境的搭建 2.2.1 环境准备 1&#xff09;安装模板虚拟机&#xff0c;IP地址 192.168.10.100&#xff0c;主机名hadoop100&#xff0c;内存41GB&#xff0c;硬盘50GB 2&#xff09;虚拟机配置 首先测试虚拟机是否可以正常上网&#xff0c;测试方法ping www.b…

配置环境windows-IIS默认拒绝put,delete的解决方案

方法一&#xff1a; <system.webServer> </system.webServer> 方法二&#xff1a;移除网站“模块”中的"webdavmodule"

【芯智雲城】Boradcom(博通) 多领域技术解决方案介绍

Broadcom Inc. 是一家全球领先的技术企业&#xff0c;业务范围囊括多种半导体、企业用软件和安全解决方案的设计、开发和供应。Broadcom 的类别领先产品组合在许多重要的市场中发挥作用&#xff0c;其中包括云、数据中心、网络、带宽、无线技术、存储&#xff0c;以及工业和企业…

元数据 - iXML

在专业的音频和视频制作中&#xff0c;元数据的准确传递对于后期制作和编辑至关重要。iXML&#xff08;iXML Metadata&#xff09;是一种开放的、可扩展的元数据规范&#xff0c;旨在在录音设备和数字音频工作站&#xff08;DAW&#xff09;之间传递详细的录音信息。 一、什么是…

单目相机和双目相机定位

1、单目相机 1.1模型 单目相机成像模型为小孔成像&#xff0c;涉及的坐标系包括世界坐标系、相机坐标系、图像坐标系以及像素坐标系。坐标系之间的转换关系如下&#xff1a; 1.2参数求解 张正友相机标定方法、设定世界坐标系精确求解 2、双目相机 2.1、模型 一般双目立体视…

低代码策略量化平台更新|大模型agents生态的一些思考

原创内容第680篇&#xff0c;专注量化投资、个人成长与财富自由。 用户判断星球会员后&#xff0c;会获得10个积分&#xff1a; 当其他用户发布策略&#xff0c;设置为下载需要积分时&#xff1a; 下载策略会扣除相应的积分&#xff0c;扣除的积分属于策略所有者。 策略运行结…

大型企业软件开发是什么样子的? - Web Dev Cody

引用自大型企业软件开发是什么样子的&#xff1f; - Web Dev Cody_哔哩哔哩_bilibili 一般来说 学技术的时候 我们会关注 开发语言特性 &#xff0c;各种高级语法糖&#xff0c;底层技术 但是很少有关注到企业里面的开发流程&#xff0c;本着以终为始&#xff08;以就业为导向…

python源码:目录文件大小排序

前言 这个代码并不难懂&#xff0c;但是在一定情况下&#xff0c;能够为你的自动化脚本提供便利。 该代码主要是&#xff1a;根据大小&#xff0c;对某个目录的下级子文件和目录进行排序。 代码 效果 代码 import osdef get_dir_size(directory):"""计算给定…

【Linux线程】Linux线程编程基础:概念、创建与管理

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux多线程 &#x1f4d2;1. 线程概念&#x1f4dc;2. 进程VS线程&#x1f4da;3. 线程控制…

SpringBoot实现接口:统一返回值、全局异常处理、Swagger接口文档

在 Spring Boot 应用中实现统一返回值和全局异常处理可以带来多方面的好处&#xff0c;这些好处不仅提升了代码的可读性和可维护性&#xff0c;还增强了应用的健壮性和用户体验。以下是一些具体的好处&#xff1a; 代码一致性&#xff1a; 通过定义统一的返回值格式&#xff…

【从零开始的LeetCode-算法】3194. 最小元素和最大元素的最小平均值

你有一个初始为空的浮点数数组 averages。另给你一个包含 n 个整数的数组 nums&#xff0c;其中 n 为偶数。 你需要重复以下步骤 n / 2 次&#xff1a; 从 nums 中移除 最小 的元素 minElement 和 最大 的元素 maxElement。将 (minElement maxElement) / 2 加入到 averages …

Apache Linkis + OceanBase:如何提升数据分析效率

计算中间件 Apache Linkis 构建了一个计算中间件层&#xff0c;以实现上层应用程序和底层数据引擎之间的连接、治理和编排。目前&#xff0c;已经支持通过数据源的功能&#xff0c;实现用户通过Linkis 对接并使用 OceanBase数据库。 本文详细阐述了在 Apache Linkis v1.3.2中&a…

零基础学习网络安全,注意这几个高效学习方法,零基础入门到精通,收藏这篇就够了

零基础学习网络安全&#xff0c;注意查收这些有效学习方法 ‍零基础怎么学网络安全?网络安全学习办法有很多&#xff0c;又高效得&#xff0c;也有低效得&#xff0c;还有无效得。今天和我一起来看看网络安全的有效学习秘籍。 ‍ 零基础从什么开始学网络安全&#xff0c;大…

七大经典排序算法优化:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序代码详解

目录 排序算法 1.插入排序 2.希尔排序 3.选择排序 4.冒泡排序 5.堆排序 6.快速排序 7.归并排序 排序算法 排序算法是一类用于将数据按照特定顺序&#xff08;如升序或降序&#xff09;排列的算法&#xff0c;常用于优化数据检索和处理。常见的排序算法包括冒泡排序、选…

【Deepin】钉钉下载文件图片闪退问题解决(临时方式)

环境 故障 下载文件、图片等闪退 解决 cd /opt/apps/com.alibabainc.dingtalk/files/7.6.0-Release.4091801/sudo rm -rf ./libstdc.so.6*注&#xff1a; 7.6.0-Release.4091801可能会略有不同&#xff0c;根据实际情况调整保险起见&#xff0c;操作第二行删除命令时&#…

第二十七篇:传输层讲解,TCP系列一

一、传输层的功能 ① 分割与重组数据 传输层也要做数据分割&#xff0c;所以必然也需要做数据重组。 ② 按端口号寻址 IP只能定位数据哪台主机&#xff0c;无法判断数据报文应该交给哪个应用&#xff0c;传输层给每个应用都设置了一个编号&#xff0c;这个编号就是端口&…