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

news2024/11/29 12:44:57

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


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

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

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

相关文章

react18中在列表项中如何使用useRef来获取每项的dom对象

在react中获取dom节点都知道用ref&#xff0c;但是在一个列表循环中&#xff0c;这样做是行不通的&#xff0c;需要做进一步的数据处理。 实现效果 需求&#xff1a;点击每张图片&#xff0c;当前图片出现在可视区域。 代码实现 .box{border: 1px solid #000;list-style: …

ParallelsDesktop20最新版本虚拟机 一键切换系统 游戏娱乐两不误

让工作生活更高效&#xff1a;Parallels Desktop 20最新版本虚拟机的神奇之处 大家好&#xff01;&#x1f44b; 今天我要跟大家安利一款让我工作效率飞升的神器——Parallels Desktop 20最新版本虚拟机。作为一个日常需要在不同操作系统间来回穿梭的人&#xff0c;这款软件简直…

react18中的计算属性及useMemo的性能优化技巧

react18里面的计算属性和使用useMemo来提升组件性能的方法 计算属性 实现效果 代码实现 函数式组件极简洁的实现&#xff0c;就这样 import { useState } from "react"; function FullName() {const [firstName, setFirstName] useState("");const [la…

OpenCV高级图形用户界面(14)交互式地选择一个或多个感兴趣区域函数selectROIs()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 允许用户在给定的图像上选择多个 ROI。 该函数创建一个窗口&#xff0c;并允许用户使用鼠标来选择多个 ROI。控制方式&#xff1a;使用空格键或…

明日周刊-第23期

十月已过半&#xff0c;气温也转凉了&#xff0c;大家注意保温哦。冬吃萝卜&#xff0c;夏吃姜&#xff0c;在快要到来的冬季大家可以选择多吃点萝卜。 配图是本周末去商场抓娃娃的时候拍的照片&#xff0c;现在抓娃娃单次普遍都控制在1块钱以下了&#xff0c;还记得多年前的抓…

智能手表PPG技术原理:【图文讲解】

光体积变化描记图法&#xff08;Photoplethysmography&#xff0c;简称PPG&#xff09;是借光电手段在活体组织中监测血液容积变化的一种无创监测方法 目前智能手表比较标配的功能&#xff1a;血糖、血压、心电、心率、血氧 1&#xff1a;人体血管 先温习一下&#xff0c;人…

Java项目-基于Springboot的智慧养老平台项目(源码+文档).zip

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、SpringClud、Vue、Mybaits Plus、ELementUI工具&…

TikTok广告账号被封?常见原因及解决方法分享

TikTok广告投放往往会给我们的账号带来高效曝光和精准流量&#xff0c;但同时许多用户也面临着一个困扰——广告账号被封禁的问题。将在此文一起商讨TikTok广告账号被封禁的原因&#xff0c;分析平台的具体规定&#xff0c;提供解决问题的应对策略&#xff0c;帮助大家有效规避…

PRCV 2024 - Day 1

2024年10月18日至10月20日&#xff0c;第七届中国模式识别与计算机视觉大会&#xff08;The 7th Chinese Conference on Pattern Recognition and Computer Vision, PRCV 2024&#xff09;在新疆乌鲁木齐的新疆国际会展中心举办&#xff0c;是国内顶级的模式识别和计算机视觉领…

专家系统简介

本文对基于规则的专家系统进行简介&#xff0c;举例专家系统的结构类似 MYCIN 系统&#xff0c;同时串联介绍专家系统的各种思想。需要注意的是&#xff0c;本文所述仅是专家系统的一种实现途径&#xff0c;其依赖规则进行知识表示和推理&#xff0c;另外还有基于语义网络、框架…

详解23种设计模式——第一部分:概述+创建型模式

目录 1. 概述 2. 创建型模式 2.1 简单&#xff08;静态&#xff09;工厂模式 2.1.1 介绍 2.1.2 实现 2.2 工厂模式 2.3 抽象工厂模式 2.4 单例模式 2.4.1 饿汉模式 2.4.2 懒汉模式 2.4.3 线程安全的懒汉式 2.4.4 DCL单例 - 高性能的懒汉式 2.5 建造者模式 2.6 原…

linux模拟:chrony同步时间

实验材料&#xff1a; 服务器&#xff1a;linux,红帽-9.1 客户端&#xff1a;linux&#xff0c;乌班图-18.4 Server/client; 安装chrony yum install -y chrony 查看chrony的状态&#xff1a; systemctl status chronyd 服务器&#xff1a; 在/etc/chrony.conf文件里面…

理解VSCODE基于配置的设置,避免臃肿

这节课我们讲两点&#xff1a; &#xff08;一&#xff09;下载、安装、汉化及美化 VSCODE&#xff1b; &#xff08;二&#xff09;理解VSCODE中基于配置&#xff08;Profiles&#xff09;的设置&#xff08;Settings&#xff09;&#xff0c;让 VSCODE 保持清爽。 &#xff0…

无极低码课程【redis windows下服务注册密码修改】

下载Windows版本的Redis linux环境 (自行下载) 1.打开官网https://redis.io/downloads/ windows环境 1.打开github https://github.com/microsoftarchive/redis/releases 然后选择你喜欢的版本zip或msi下载 2.这里下载zip版,解压后后,打开安装目录 3.双击redis-server…

学习莫烦python---神经网络

一、卷积神经网络区别 1、“卷积” 和 “神经网络”. 卷积也就是说神经网络不再是对每个像素的输入信息做处理了,而是图片上每一小块像素区域进行处理, 这种做法加强了图片信息的连续性. 使得神经网络能看到图形, 而非一个点. 这种做法同时也加深了神经网络对图片的理解 –翻译…

快充协议有哪些,都有哪些特点

什么是PD协议 PD协议是一种充电协议&#xff0c;全称为“USB Power Delivery&#xff08;USB PD&#xff09;”&#xff0c;是由USB-IF&#xff08;USB Implementers Forum&#xff09;组织制定的一种标准协议‌。它是一种基于USB接口的快速充电技术&#xff0c;可以实现高达1…

【无人机设计与控制】基于环形拓扑的多目标粒子群优化算法(MO_Ring_PSO_SCD)求解无人机

摘要 本文提出了一种基于环形拓扑的多目标粒子群优化算法 (MO-Ring-PSO-SCD) 用于解决无人机的三维路径规划问题。该算法同时优化了无人机路径的路径成本和威胁成本&#xff0c;通过粒子群算法的多目标优化能力实现路径选择。实验结果表明&#xff0c;与传统算法相比&#xff…

RFID在半导体天车的问题解决方案

RFID在半导体天车的问题解决方案 目前苏州某科技公司的半导体天车目前现阶段存在问题&#xff1a; &#xff08;1&#xff09;传统8寸晶圆加工过程中涉及几十道工序&#xff0c;目前都是采用人工搬运&#xff0c;容易产生污染物导致晶圆损坏&#xff0c;速度也比较慢&#xf…

自动驾驶系列—自动驾驶测试前的必备流程:车辆准备平台深度解析

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

Java笔试04

采用FIFO&#xff08;先进先出&#xff09;页面置换算法&#xff0c;可能会产生 抖动现象&#xff1a;抖动现象是指频繁地进行页面置换&#xff0c;导致系统资源大部分时间用于页面置换而不是实际的计算工作。FIFO算法由于其简单的先进先出特性&#xff0c;可能会导致频繁的页面…