PyQt5 使用 QLabel 实现图像 360度 不间断旋转

news/2024/10/8 18:10:38

PyQt5 使用 QLabel 实现图像 360度 不间断旋转

当我们需要实现让一个图像 360度 旋转时,比如:音乐播放器中播放时,歌曲封面的旋转效果,你可以尝试使用下面的方法

代码结构

本文中全部代码全在test_QLabel_whirling.py这一个文件中编码,步骤中有变动的地方会注释标注,无改动的不会重复显示出来,需要看完整代码的,可直接移步到末尾。

一. 创建测试页面

创建一个测试页面,其中主要是放置了2个QLabel,一个QProgressBar,其中一个QLabel,用于实现图像旋转

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QLabel_whirling.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 图像 360 度旋转
"""
from PyQt5.QtGui import QMovie
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QFrame, QProgressBar
from PyQt5.QtGui import QPixmap, QTransform
from PyQt5.QtCore import QTimer, Qt, QMetaObject, QCoreApplicationclass Ui_Whirling(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(712, 76)self.gridLayout_2 = QGridLayout(Form)self.gridLayout_2.setObjectName("gridLayout_2")# 创建一个 QFrame,用于放置其余组件self.frame = QFrame(Form)self.frame.setFrameShape(QFrame.StyledPanel)self.frame.setFrameShadow(QFrame.Raised)self.frame.setObjectName("frame")# 网格布局self.gridLayout = QGridLayout(self.frame)self.gridLayout.setObjectName("gridLayout")# 创建一个 QLabel,其实这个没啥用self.label_2 = QLabel(self.frame)self.label_2.setObjectName("label_2")self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)# 创建一个 QProgressBar,其实这个没啥用self.progressBar = QProgressBar(self.frame)self.progressBar.setProperty("value", 24)self.progressBar.setObjectName("progressBar")self.gridLayout.addWidget(self.progressBar, 1, 1, 1, 1)# 创建一个 QLabel,用于实现图片旋转self.label = QLabel(self.frame)self.label.setObjectName("label")self.gridLayout.addWidget(self.label, 0, 0, 2, 1)self.gridLayout_2.addWidget(self.frame, 0, 0, 1, 1)self.retranslateUi(Form)QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QCoreApplication.translateForm.setWindowTitle(_translate("Form", "图片 360° 旋转"))self.label_2.setText(_translate("Form", "<<--- 左侧图片 360° 旋转"))self.label.setText(_translate("Form", "图片"))class GIFRotatingLabel(QWidget, Ui_Whirling):def __init__(self):super().__init__()self.setupUi(self)if __name__ == "__main__":import sysapp = QApplication(sys.argv)w = GIFRotatingLabel()w.show()sys.exit(app.exec_())

测试页面如图:
image

二. 实现方式

方式一:直接使用一个 旋转的gif实现

这种方式代码量最小,如这样的gif图
image

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QLabel_whirling.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 图像 360 度旋转
"""class Ui_Whirling(object):...  # 忽略,无改动class GIFRotatingLabel(QWidget, Ui_Whirling):"""GIF实现"""def __init__(self):super().__init__()self.setupUi(self)movie = QMovie(r"image\34.gif")  # 替换为你的图像路径self.label.setMovie(movie)movie.start()

效果如下,此效果图中的抖动是截图导致的,实际是平滑的:
image

方式二:使用QTransform重新创建对象并应用

我们使用 QTimer 定期调用 rotate_image 方法来更新图像的旋转角度。每次调用时,创建一个新的 QTransform 对象并应用旋转,然后更新 QLabel 中的图像。调整定时器的间隔和角度增量,就可以改变旋转速度。

代码中使用的create_rounded_pixmap方法,是将正方形图片通过设置圆角的方式,修改为圆形,具体代码详情看这里

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QLabel_whirling.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 图像 360 度旋转
"""class Ui_Whirling(object):...  # 忽略,无改动class RotatingLabel(QWidget, Ui_Whirling):"""QTransform"""def __init__(self):super().__init__()self.setupUi(self)pixmap = QPixmap(r'image\20.png')  # 替换为你的图像路径,且必须是正方形# 创建圆形图像self.rounded_pixmap = create_rounded_pixmap(pixmap, pixmap.height() / 2)self.label.setPixmap(self.rounded_pixmap)  # 设置图像self.label.setFixedSize(pixmap.width(), pixmap.height())  # 设置 QLabel 的固定大小self.label.setAlignment(Qt.AlignCenter)  # 使 QLabel 在中心self.angle = 0  # 初始角度# 创建定时器self.timer = QTimer(self)self.timer.timeout.connect(self.rotate_image)self.timer.start(10)  # 每10毫秒更新一次def rotate_image(self):self.angle = (self.angle + 1) % 360  # 每次增加1度# transform = QTransform().rotate(self.angle)# 始终保持几何中心旋转transform = QTransform().translate(self.rounded_pixmap.width() / 2, self.rounded_pixmap.height() / 2) \.rotate(self.angle) \.translate(-self.rounded_pixmap.width() / 2, -self.rounded_pixmap.height() / 2)rotated_pixmap = self.rounded_pixmap.transformed(transform, mode=1)  # 使用平滑缩放self.label.setPixmap(rotated_pixmap)

效果如下,此效果图中的抖动是截图导致的,实际是平滑的:
image

四. 完整代码

使用时,只使用self.label相关的设置即可,完整代码如下:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QLabel_whirling.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 图像 360 度旋转
"""
from PyQt5.QtGui import QMovie
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QFrame, QProgressBar
from PyQt5.QtGui import QPixmap, QTransform
from PyQt5.QtCore import QTimer, Qt, QMetaObject, QCoreApplicationfrom lib.rounded_pixmap import create_rounded_pixmapclass Ui_Whirling(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(712, 76)self.gridLayout_2 = QGridLayout(Form)self.gridLayout_2.setObjectName("gridLayout_2")# 创建一个 QFrame,用于放置其余组件self.frame = QFrame(Form)self.frame.setFrameShape(QFrame.StyledPanel)self.frame.setFrameShadow(QFrame.Raised)self.frame.setObjectName("frame")# 网格布局self.gridLayout = QGridLayout(self.frame)self.gridLayout.setObjectName("gridLayout")# 创建一个 QLabel,其实这个没啥用self.label_2 = QLabel(self.frame)self.label_2.setObjectName("label_2")self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)# 创建一个 QProgressBar,其实这个没啥用self.progressBar = QProgressBar(self.frame)self.progressBar.setProperty("value", 24)self.progressBar.setObjectName("progressBar")self.gridLayout.addWidget(self.progressBar, 1, 1, 1, 1)# 创建一个 QLabel,用于实现图片旋转self.label = QLabel(self.frame)self.label.setObjectName("label")self.gridLayout.addWidget(self.label, 0, 0, 2, 1)self.gridLayout_2.addWidget(self.frame, 0, 0, 1, 1)self.retranslateUi(Form)QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QCoreApplication.translateForm.setWindowTitle(_translate("Form", "图片 360° 旋转"))self.label_2.setText(_translate("Form", "<<--- 左侧图片 360° 旋转"))self.label.setText(_translate("Form", "图片"))class GIFRotatingLabel(QWidget, Ui_Whirling):"""GIF实现"""def __init__(self):super().__init__()self.setupUi(self)movie = QMovie(r"image\34.gif")  # 替换为你的图像路径self.label.setMovie(movie)movie.start()class RotatingLabel(QWidget, Ui_Whirling):"""QTransform"""def __init__(self):super().__init__()self.setupUi(self)pixmap = QPixmap(r'image\20.png')  # 替换为你的图像路径,且必须是正方形# 创建圆形图像self.rounded_pixmap = create_rounded_pixmap(pixmap, pixmap.height() / 2)self.label.setPixmap(self.rounded_pixmap)  # 设置图像self.label.setFixedSize(pixmap.width(), pixmap.height())  # 设置 QLabel 的固定大小self.label.setAlignment(Qt.AlignCenter)  # 使 QLabel 在中心self.angle = 0  # 初始角度# 创建定时器self.timer = QTimer(self)self.timer.timeout.connect(self.rotate_image)self.timer.start(10)  # 每10毫秒更新一次def rotate_image(self):self.angle = (self.angle + 1) % 360  # 每次增加1度# transform = QTransform().rotate(self.angle)# 始终保持几何中心旋转transform = QTransform().translate(self.rounded_pixmap.width() / 2, self.rounded_pixmap.height() / 2) \.rotate(self.angle) \.translate(-self.rounded_pixmap.width() / 2, -self.rounded_pixmap.height() / 2)rotated_pixmap = self.rounded_pixmap.transformed(transform, mode=1)  # 使用平滑缩放self.label.setPixmap(rotated_pixmap)if __name__ == '__main__':import sysapp = QApplication(sys.argv)window = RotatingLabel()# window = GIFRotatingLabel()window.show()sys.exit(app.exec_())

本文章的原文地址
GitHub主页

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

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

相关文章

systemverilog笔记

变量类型变量名 状态数 是否带符号 比特数logic 4 无 1bit 2 无 1byte 2 有 8shortint 2 有 16int 2 有 32longint 2 有 64integer 4 有 32time 4 无 64$isunknown(表达式):在表达式任意位出现X或者Z时返回1。 数组 数组初始化 使用单引号加大括号数组遍历 $size(数组)会返回

DSP概述及应用——TMS320DM6437ZDU4、TMS320DM6437ZWT6、TMS320DM6437ZWT7数字媒体处理器

TMS320DM6437采用基于超标量架构的C64x+内核,具有高效的乘法累加单元和多格式指令集,能够在单个时钟周期内执行两条指令,大大提高了运算速度和效率。概述:TMS320DM6437是一款DSP芯片,具有强大的处理能力和丰富的功能模块。 TMS320DM6437采用基于超标量架构的C64x+内核,具…

csp-s模拟10

rank 31,垫底了,T1 0pts,T2 18pts,T3 0pts,T4 50pts 状态有点不好,策略有问题,T4是可以切的,但是不知道为什么弃了。T1不会线性基寄。T3 奇怪结论题,T2 结论题。 在猜结论上还是不行。 T1 欧几里得的噩梦 用到了线性基线性无关的性质,将两个数连边,把环去掉,并查集判…

二叉树的概念、表示法、性质和操作

本文记述了二叉树的基本概念、表示法、性质和操作。 ◆ 概念 二叉树(以下也简称树)是一种存放多个元素的数据结构。每个元素称为结点,每个结点有左、右两个链接,每个链接要么指向其他结点,要么是空链接。 某个结点是它的左、右链接指向的结点的父结点,被指向的结点是其父…

Springboot中统一启动多个socketIO

前言 这篇随笔属实没想到一个好名字,起因是在项目中遇到了一个springboot服务会发出多个socket服务的场景,而且我们使用的是socketIO服务,为了减少调试工作和重复的开发工作,让开发在项目中专注于业务编写,因此封装了一个在启动springboot服务时,自动创建socketIONamespa…

软件工程第二次结对作业

软件工程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13281作业目标 基于第一次结对作业项目程序的实现学号 102201129合作伙伴 102201127项目分工: 102201129周鑫: 前端开发: 设计和实现用户界面。 确保界面响…

CSP 模拟9

CSP 模拟9 我也不明白学校模拟赛什么命名逻辑,凑合着看吧最唐的一集 邻面合并 这个直接状压就做完了,赛时早早想到做法,但是因为自己太唐把 \(0\) 写成 \(1\),在优秀大样例的助攻下挂掉 \(50\)点击查看代码 #include<bits/stdc++.h> using namespace std; using llt=…

南沙C++信奥赛陈老师解一本通题 1297:公共子序列

​【题目描述】我们称序列Z=<z1,z2,...,zk>Z=<z1,z2,...,zk>是序列X=<x1,x2,...,xm>X=<x1,x2,...,xm>的子序列当且仅当存在严格上升的序列<i1,i2,...,ik><i1,i2,...,ik>,使得对j=1,2,...,k,有xij=zjxij=zj。比如Z=<a,b,f,c> 是X=&l…