Qt实现图片旋转的几种方式(全)

news2025/1/16 18:05:50

目录

一、用手搓(QPainter)

二、使用 QGraphicsView 和 QGraphicsPixmapItem

三、使用 QTransform 实现图像旋转

四、利用 OpenGL


实现旋转图像的效果有几种不同的方法,其中常见的包括:

  1. 手动旋转绘制: 使用 QPainter 的旋转函数,手动计算旋转后的坐标并绘制图像。这种方式需要自己处理旋转后的坐标变换,相对复杂一些。

  2. 使用 QGraphicsView 和 QGraphicsPixmapItem: 使用 QGraphicsView 架构绘制图形对象,并在 QGraphicsScene 中添加 QGraphicsPixmapItem,然后通过旋转 QGraphicsPixmapItem 实现图像旋转。

  3. 使用 QTransform: 使用 QTransform 类来应用变换,通过旋转矩阵来对图像进行旋转,然后使用 QPainter 绘制旋转后的图像。这种方法能够简化坐标变换的操作。

  4. 利用 OpenGL: 利用 Qt 的 QOpenGLWidget 和 OpenGL 的旋转操作,在 OpenGL 上下文中进行图像的绘制和旋转。这种方法适用于需要更高级别的图形操作和性能要求较高的场景。

每种方法都有其特点和适用场景,选择其中一种取决于你的需求和熟悉程度。通常情况下,QTransform 是实现图像旋转最常用且较为简便的方式。

一、用手搓(QPainter

  1. 创建绘图设备(QPainter): 首先,需要创建一个 QPainter 对象,用于执行绘图操作。

  2. 设置绘图参数: 在进行绘图之前,可以通过 QPainter 的函数设置渲染参数,如反锯齿等。

  3. 加载图像: 使用 QPixmap 加载需要绘制的图像。

  4. 设置绘图变换: 使用 QPainter 的变换函数(例如 translate、rotate 等),将绘图坐标系转换到图像的中心,并按需求进行旋转。

  5. 绘制图像: 使用 QPainter 的 drawPixmap 函数,在指定的位置绘制图像。

  6. 重置绘图变换(可选): 如果在绘制其他内容之前需要恢复坐标系变换,则可以使用 QPainter 的 resetTransform 函数重置坐标系。

  7. 完成绘图: 绘图完成后,程序会自动将绘图设备的内容显示到窗口上,或者在需要时手动调用 update 函数触发窗口的重绘。

​手搓代码:https://download.csdn.net/download/qq_43445867/88562187

二、使用 QGraphicsView 和 QGraphicsPixmapItem

1、创建一个 QGraphicsScene 对象。然后加载图像到 QPixmap 中,

2、创建 QGraphicsPixmapItem 对象,并将图像加载到这个 QGraphicsPixmapItem 中。

3、分别使用 setPos()setRotation() 函数,设置图像的位置和旋转角度。

4、将 QGraphicsPixmapItem 添加到 QGraphicsScene

5、创建一个 QGraphicsView 对象,并将 QGraphicsScene 设置为 QGraphicsView 的场景,最终显示了这个 QGraphicsView

6、通过修改 setPos()setRotation() 函数中的参数,可以设置图像的位置和旋转角度。这种方法相比手动绘制更简单,并且使用 QGraphicsViewQGraphicsPixmapItem 更方便地进行图像的操作和显示。

7、创建一个定时器 QTimer,并将其连接到一个 Lambda 函数,Lambda 函数中每次定时器超时时都会更新图像的旋转角度。在每个超时事件中,图像的旋转角度增加 1 度,并通过 setRotation() 函数应用于 QGraphicsPixmapItem,从而使图像持续旋转。然后使用 timer.start() 启动定时器,并设定每 30 毫秒更新一次旋转角度

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QPixmap>
#include <QTimer>
​
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
​
    // 创建 QGraphicsScene
    QGraphicsScene scene;
​
    // 加载图像到 QPixmap
    QPixmap pixmap("statI.png");
​
    // 创建 QGraphicsPixmapItem 并将图像加载到 QGraphicsPixmapItem 中
    QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem(pixmap);
​
    // 设置图像的旋转中心点为图像中心
    pixmapItem->setTransformOriginPoint(pixmap.width() / 2, pixmap.height() / 2);
​
    // 将 QGraphicsPixmapItem 添加到 QGraphicsScene 中
    scene.addItem(pixmapItem);
​
    // 创建 QGraphicsView,并将 QGraphicsScene 设置为它的场景
    QGraphicsView view(&scene);
​
    // 显示 QGraphicsView
    view.show();
​
    // 创建定时器,并连接到槽函数以持续更新旋转角度
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&]() {
        static qreal rotationAngle = 0.0;
        rotationAngle += 1.0; // 每次增加旋转角度
​
        // 将旋转角度应用于 QGraphicsPixmapItem
        pixmapItem->setRotation(rotationAngle);
    });
    timer.start(30); // 每 30 毫秒更新一次旋转角度
​
    return app.exec();
}

三、使用 QTransform 实现图像旋转

使用 Qt 提供的图形组件和定时器来实现图像的加载和旋转,通过设置合适的中心点以及应用 QTransform 进行变换操作,达到了让图像围绕自身中心点旋转的效果。

  // 创建 QTransform 对象,并应用旋转变换
  QTransform transform;
  transform.translate(pixmap.width() / 2, pi
  transform.rotate(rotationAngle); // 绕中心点旋转
  transform.translate(-pixmap.width() / 2, -
  // 将变换应用于 QGraphicsPixmapItem
  pixmapItem->setTransform(transform);

通过使用 QGraphicsSceneQGraphicsViewQGraphicsPixmapItem 这些 Qt 图形组件来显示图像,并使用 QTimer 定时器来控制图像的旋转。

  1. 加载图像: 使用 QPixmap 加载图片,并将其放置在 QGraphicsPixmapItem 中,然后将该项添加到 QGraphicsScene 中,最终显示在 QGraphicsView 中。

  2. 设置中心点:QGraphicsPixmapItem 中使用 setTransformOriginPoint() 将图像的中心点设置为图像的中心。

  3. 定时旋转: 创建 QTimer 定时器,每当定时器超时时,更新旋转角度。在超时槽函数中,使用 QTransform 进行变换处理。首先移动图像的原点到中心点,然后进行旋转,最后再将原点移回原位置。这样就实现了图像围绕自身中心点持续旋转的效果。

  4. 显示图像:QGraphicsView 显示出来,图像会根据定时器的触发事件,在固定时间间隔内持续旋转显示。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QPixmap>
#include <QTransform>
#include <QTimer>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建 QGraphicsScene
    QGraphicsScene scene;

    // 加载图像到 QPixmap
    QPixmap pixmap(":/path/to/your/image.png");

    // 创建 QGraphicsPixmapItem 并将图像加载到 QGraphicsPixmapItem 中
    QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem(pixmap);

    // 设置图像的中心点为原点
    pixmapItem->setTransformOriginPoint(pixmap.width() / 2, pixmap.height() / 2);

    // 将 QGraphicsPixmapItem 添加到 QGraphicsScene 中
    scene.addItem(pixmapItem);

    // 创建 QGraphicsView,并将 QGraphicsScene 设置为它的场景
    QGraphicsView view(&scene);

    // 显示 QGraphicsView
    view.show();

    // 创建定时器,并连接到槽函数以持续更新旋转角度
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&]() {
        static qreal rotationAngle = 0.0;
        rotationAngle += 1.0; // 每次增加旋转角度

        // 创建 QTransform 对象,并应用旋转变换
        QTransform transform;
        transform.translate(pixmap.width() / 2, pixmap.height() / 2); // 将原点移动到中心
        transform.rotate(rotationAngle); // 绕中心点旋转
        transform.translate(-pixmap.width() / 2, -pixmap.height() / 2); // 将原点移回原位

        // 将变换应用于 QGraphicsPixmapItem
        pixmapItem->setTransform(transform);
    });
    timer.start(30); // 每 30 毫秒更新一次旋转角度

    return app.exec();
}

四、利用 OpenGL

待研究

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

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

相关文章

Linux中的进程程序替换

Linux中的进程程序替换 1. 替换原理2. 替换函数3. 函数解释4. 命名理解程序替换的意义 1. 替换原理 替换原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的…

Java Stream中的API你都用过了吗?

公众号「架构成长指南」&#xff0c;专注于生产实践、云原生、分布式系统、大数据技术分享。 在本教程中&#xff0c;您将通过大量示例来学习 Java 8 Stream API。 Java 在 Java 8 中提供了一个新的附加包&#xff0c;称为 java.util.stream。该包由类、接口和枚举组成&#x…

web需求记录

需求1&#xff1a;根据后端传过来的设备名:DESKTOP-4DQRGQB&#xff0c;以及mac:e0:be:03:74:40:0b&#xff1b;iQOO-8&#xff0c;mac:b0:33:66:38:c3:25&#xff0c;用web option 是动态增加的&#xff08;也就是那个选择框里面的东西是根据后端传过来的值动态增加的&#xf…

基于Qt的UDP通信、TCP文件传输程序的设计与实现——QQ聊天群聊

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言一…

【C++】vector的介绍与使用

&#x1f9d1;‍&#x1f393;个人主页&#xff1a;简 料 &#x1f3c6;所属专栏&#xff1a;C &#x1f3c6;个人社区&#xff1a;越努力越幸运社区 &#x1f3c6;简 介&#xff1a;简料简料&#xff0c;简单有料~在校大学生一枚&#xff0c;专注C/C/GO的干货分…

【Vue】自定义指令

自定义指令 自定义指令就是自己定义的指令&#xff0c;是对 DOM 元素进行底层操作封装 ,程序化地控制 DOM&#xff0c;拓展额外的功能 全局定义 Vue.directive(指令名字, definition) 指令名&#xff1a;不包括v-前缀&#xff0c;使用时候包括v-&#xff0c;v-指令名defini…

VPS配置了swap没发挥作用怎么办

1 swap配置了但没用上 我的服务器内存是2G&#xff0c;装多一点东西就不够用&#xff0c;于是我给他分配了2G的swap&#xff0c;等了几小时&#xff0c;swap还是一点都没有使用 Linux中Swap&#xff08;即&#xff1a;交换分区&#xff09;&#xff0c;类似于Windows的虚拟内存…

IT变更管理实现服务台高效协同

在当今数字化时代&#xff0c;IT变更管理是IT管理员在服务台中必须面对的重要挑战之一。随着技术的不断发展和市场的快速变化&#xff0c;管理员需要定期进行IT系统和流程的变更&#xff0c;在确保业务稳定性的同时还需提高效率和准确率。 1、全方位的变更计划 IT中应该有一个全…

如何使用YOLOv8代码框架中的RT-DETR

1. RT-DETR RT-DETR是由由此&#xff0c;百度推出了——RT-DETR (Real-Time DEtection TRansformer) &#xff0c;一种基于 DETR 架构的实时端到端检测器&#xff0c;其在速度和精度上取得了 SOTA 性能。 RT-DETR开源的代码在百度自己的飞桨paddlepaddle上&#xff0c;因此非…

Confluence 未授权漏洞分析(CVE-2023-22515)

0x01 漏洞描述 Confluence 是由 Atlassian 开发的企业级协作软件。2023年10月&#xff0c;Atlassian 官方披露 CVE-2023-22515 Atlassian Confluence Data Center & Server 权限提升漏洞。攻击者可构造恶意请求创建管理员&#xff0c;从而登录系统&#xff0c;造成敏感信息…

BUUCTF [SWPU2019]神奇的二维码 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件&#xff0c;得到一个.png图片。 解题思路&#xff1a; 1、使用QR research扫一下&#xff0c;得到“swpuctf{flag_is_not_here}”的提示。 2、放到0…

HTML新手入门笔记整理:HTML基本介绍

网页 静态页面 仅可供用户浏览&#xff0c;不具备与服务器交互的功能。 动态页面 可供用户浏览&#xff0c;具备与服务器交互的功能。 HTML HTML&#xff0c;全称HyperText Markup Language&#xff08;超文本标记语言&#xff09;,是一种用于创建网页的标准标记语言。用于…

经典双指针算法试题(二)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、有效三角形的个数1、题目讲解2、讲解算法原理3、代码实现 二、查找总价格为目标值的两个商…

MCU 的 TOP 15 图形GUI库:选择最适合你的图形用户界面(一)

在嵌入式系统开发中&#xff0c;选择一个合适的图形用户界面&#xff08;GUI&#xff09;库是至关重要的。在屏幕上显示的时候&#xff0c;使用现成的图形库&#xff0c;这样开发人员就不需要弄清楚底层任务&#xff0c;例如如何绘制像素、线条、形状&#xff0c;如果再高级一点…

栈和队列java实现

栈和队列都是动态集合&#xff0c;且在其上进行DELETE操作所移除的元素是预先设定的。在栈中&#xff0c;被删除的是最近插入的元素&#xff1a;栈实现的是一种后进先出&#xff08;last-in&#xff0c;first-out&#xff0c;LIFO&#xff09; 策略。在队列中&#xff0c;被删去…

问鼎web服务

华子目录 www简介常见Web服务程序介绍&#xff1a;服务器主机主要数据浏览器网址及http介绍urlhttp请求方法 http协议请求的工作流程www服务器类型静态网站动态网站 快速安装Apache安装准备工作httpd所需目录主配置文件 实验操作 www简介 Web网络服务也叫www&#xff08;world…

K8S部署mongodb-sharded-cluster(7.0.2)副本分片

添加源 helm repo add bitnami https://charts.bitnami.com/bitnami指定版本拉取 helm pull --repo https://charts.bitnami.com/bitnami mongodb-sharded --version 7.0.5安装时选择SCRAM-SHA-1默认是SCRAM-SHA-256 helm install -n prod mymongodb mongodb-sharded --value…

优先级队列(priority_queue)

文章目录 优先级队列的定义定义&#xff1a;接口头文件优先队列和堆的关系使用&#xff1a;排序的规则容器 仿函数应用 队列存指针问题&#xff1a; 优先级队列的定义 定义&#xff1a; 黄色部分是仿函数 接口 头文件 这里不需要包含其他的头文件只需要使用队列的头文件就可以…

蓝桥杯每日一题2023.11.22

题目描述 题目分析 由题目知其每个品牌积分一定小于315故直接暴力枚举每个品牌如果符合要求直接输出即可 &#xff08;答案&#xff1a;150&#xff09; #include<bits/stdc.h> using namespace std; int main() {for(int i 1; i < 315; i ){for(int j 1; j <…

三、防火墙-源NAT

学习防火墙之前&#xff0c;对路由交换应要有一定的认识 源NAT基本原理1.1.NAT No-PAT1.2.NAPT1.3.出接口地址方式&#xff08;Easy IP&#xff09;1.4.Smart NAT1.5.三元组 NAT1.6.多出口场景下的源NAT 总结延伸 ——————————————————————————————…