Python玩个球,如何用PyQt5实现足球射门动画?

2023-12-29 06:08

本文主要是介绍Python玩个球,如何用PyQt5实现足球射门动画?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文转自:https://zhuanlan.zhihu.com/p/42570471作者:州的先生

QT作为一个全面的桌面应用程序开发包,其自然提供了对图像的动画支持。本篇文章中,就来简单地在PYQt5中使用Animation动画功能实现一个足球射门的动画效果。

本篇将会依次完成以下功能:

  • 在GUI界面中显示一个图片(用一个足球做演示);
  • 点击按钮实现足球的直线射门动画;
  • 点击按钮实现足球的曲线射门动画;

一、在图形界面显示图片的两种方法

一般情况下,想要在GUI中显示图片,我们会通过:

  • 实例化一个QLable()部件;
  • 实例化一个QPixmap()图形类;
  • 通过QLabel()部件的setPixmap()方法设置QLabel()部件的图形;
  • 更多Python视频、源码、资料加群683380553免费获取

就像如下代码所示:

# coding:utf-8from PyQt5 import QtGui,QtWidgets
import sysclass MainUi(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("动画使用-zmister.com") # 设置窗口标题self.resize(400,200) # 规定窗口大小self.main_widget = QtWidgets.QWidget() # 创建一个widget部件self.label = QtWidgets.QLabel(self.main_widget) # 创建一个文本标签部件png = QtGui.QPixmap() # 创建一个绘图类png.load("logo.png") # 从pngz中加载一个图片self.label.setPixmap(png) # 设置文本标签的图形self.setCentralWidget(self.main_widget)if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)gui = MainUi()gui.show()sys.exit(app.exec_())

运行上述代码,我们将会得到如下所示的图形界面:

 

但是这种方法没有办法实现对图片更多的控制。为了更好地对图形界面中的图片进行控制和管理,我们还需要使用到其他的类,比如QtWidgets中的QGraphicsScene类,QGraphicsScene提供了一个场景,用于对2D图形进行管理。同时,为了展示QGraphicsScene中的内容,我们还需要使用到QtWidgets中的QGraphicsView类来提供一个视图部件。

下面,我们就通过一个简单的例子来了解一下QGraphicsScene类和QGraphicsView类的使用。

首先是完整的代码,如下所示:

# coding:utf-8from PyQt5 import QtGui,QtWidgets,QtCore
import sysclass MainUi(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("动画使用-zmister.com") # 设置窗口标题self.resize(400,200) # 规定窗口大小self.main_widget = QtWidgets.QWidget() # 创建一个widget部件self.grapview = QtWidgets.QGraphicsView(self.main_widget) # 创建一个图形视图,继承自main_widgetself.grapview.setGeometry(QtCore.QRect(10, 10, 380, 180)) # 设置图形视图的矩形区域self.scene = QtWidgets.QGraphicsScene() # 创建一个图形管理场景self.grapview.setScene(self.scene)png = QtGui.QPixmap() # 创建一个绘图类png.load("logo.png") # 从png中加载一个图片item = QtWidgets.QGraphicsPixmapItem(png) #self.scene.addItem(item)self.setCentralWidget(self.main_widget)if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)gui = MainUi()gui.show()sys.exit(app.exec_())

在这里面,基础的窗口代码与之前的代码类似,有区别且最核心的为以下几行代码。

首先,我们实例化创建了一个用于展示图形场景的图形视图QGraphicsView(),将它继承自self.main_widget主窗口部件:

self.grapview = QtWidgets.QGraphicsView(self.main_widget)

然后,我们实例化创建了一个图形场景管理类QGraphicsScene(),并通过setScene()方法将图形视图self.grapview的图形场景设置为刚刚实例化创建的QGraphicsScene():

self.scene = QtWidgets.QGraphicsScene()
self.grapview.setScene(self.scene)

最后,我们通过QPixmap()创建并加载了一个图片,将其添加到图形项目QGraphicsPixmapItem()中,并通过addItem()方法将图形项目添加到图形场景管理self.scene中:

png = QtGui.QPixmap()
png.load("logo.png")
item = QtWidgets.QGraphicsPixmapItem(png)
self.scene.addItem(item)

如此,我们就完成了通过QGraphicsView()类和QGraphicsScene()类在图形界面(GUI)中展示图片的功能,运行完整的代码,其显示出来的图形界面程序如下图所示:

 

 

二、几行代码射个门

上面我们通过两种不同的方式实现了图片在图形界面中的展示,接下来,我们借助QtCore中的QPropertyAnimation()来实现图片的动画效果。

QPropertyAnimation()类主要依靠操纵对象的QT属性来实现动画效果,其有几个比较主要的方法:

  • start():用于启动动画;
  • stop():用于停止动画;
  • setStartValue():用于设置动画的起始值;
  • setEndValue():用于设置动画的结束值;
  • setDuration():用于设置动画的持续时间;
  • setKeyValueAt():用于在特定时间创建一个关键的动画帧动作;
  • setLoopCount():用于设置动画的循环次数;

下面我们就使用QPropertyAnimation()类实现图片的动画。为了动画的效果比5毛特效要好一点,州的先生(公众号:zmister2016)在阿里的图标库iconfont里找了一个小足球和球门的图标,嗯,就像这样:

 

 

 

 

然后,我们创建一个图形界面,里面包含一个按钮、一个小球和一个球门的图片:

# coding:utf-8
from PyQt5 import QtGui,QtWidgets,QtCore
import sysclass MainUi(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("动画使用-zmister.com") # 设置窗口标题self.resize(400,200) # 规定窗口大小self.main_widget = QtWidgets.QWidget() # 创建一个widget部件self.button = QtWidgets.QPushButton('射门',self.main_widget) # 创建一个按钮self.button.setGeometry(10,10,60,30) # 设置按钮位置self.label = QtWidgets.QLabel(self.main_widget) # 创建一个文本标签部件用于显示足球self.label.setGeometry(50,80,50,50) # 设置足球位置png = QtGui.QPixmap()  # 创建一个绘图类png.load("football.png")  # 从png中加载一个图片self.label.setPixmap(png)  # 设置文本标签的图形self.label.setScaledContents(True)self.qiumen = QtWidgets.QLabel(self.main_widget)  # 创建一个文本标签部件用于显示球门self.qiumen.setGeometry(345, 75, 50, 50)  # 设置球门位置pngqiumen = QtGui.QPixmap()  # 创建一个绘图类pngqiumen.load("qiumen.png")  # 从png中加载一个图片self.qiumen.setPixmap(pngqiumen)  # 设置文本标签的图形self.setCentralWidget(self.main_widget)if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)gui = MainUi()gui.show()sys.exit(app.exec_())

运行上述代码,我们会得到一个如下图所示的图形界面:

 

 

我们的目的是想让图形界面中的小足球通过按钮控制,进入到球门中。接下来,我们就通过QPropertyAnimation()类来实现这个效果。

在MainUi()中新建一个名为shoot()的方法,在其中写入以下代码:

self.anim = QtCore.QPropertyAnimation(self.label,b'geometry') # 设置动画的对象及其属性
self.anim.setDuration(2000) # 设置动画间隔时间
self.anim.setStartValue(QtCore.QRect(50,80,50,50)) # 设置动画对象的起始属性
self.anim.setEndValue(QtCore.QRect(360, 90, 10, 10)) # 设置动画对象的结束属性
self.anim.start() # 启动动画

最后,我们再讲按钮的点击信号绑定到shoot()方法上:

self.button.clicked.connect(self.shoot)

完整的代码如下所示:

# coding:utf-8
from PyQt5 import QtGui,QtWidgets,QtCore
import sysclass MainUi(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("动画使用-zmister.com") # 设置窗口标题self.resize(400,200) # 规定窗口大小self.main_widget = QtWidgets.QWidget() # 创建一个widget部件self.button = QtWidgets.QPushButton('射门',self.main_widget) # 创建一个按钮self.button.setGeometry(10,10,60,30) # 设置按钮位置self.button.clicked.connect(self.shoot)self.label = QtWidgets.QLabel(self.main_widget) # 创建一个文本标签部件用于显示足球self.label.setGeometry(50,80,50,50) # 设置足球位置png = QtGui.QPixmap()  # 创建一个绘图类png.load("football.png")  # 从png中加载一个图片self.label.setPixmap(png)  # 设置文本标签的图形self.label.setScaledContents(True) # 图片随文本部件的大小变动self.qiumen = QtWidgets.QLabel(self.main_widget)  # 创建一个文本标签部件用于显示球门self.qiumen.setGeometry(345, 75, 50, 50)  # 设置球门位置pngqiumen = QtGui.QPixmap()  # 创建一个绘图类pngqiumen.load("qiumen.png")  # 从png中加载一个图片self.qiumen.setPixmap(pngqiumen)  # 设置文本标签的图形self.setCentralWidget(self.main_widget)def shoot(self):self.anim = QtCore.QPropertyAnimation(self.label,b'geometry') # 设置动画的对象及其属性self.anim.setDuration(2000) # 设置动画间隔时间self.anim.setStartValue(QtCore.QRect(50,80,50,50)) # 设置动画对象的起始属性self.anim.setEndValue(QtCore.QRect(360, 90, 10, 10)) # 设置动画对象的结束属性self.anim.start() # 启动动画if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)gui = MainUi()gui.show()sys.exit(app.exec_())

运行上述代码,点击“射门”按钮,我们将会得到如下动图所示的动画:

 

 

这样,通过QPropertyAnimation()的setDuration()方法、setStartValue()方法、setEndValue()方法我们就实现了一个简单的动画。

三、圆月弯刀继续射门

但是上面的射门动画是一条直线将小足球移动到了球门之内,简单粗暴欠缺了些许美感,下面,我们让这个射门换一种方式,用圆月弯刀的香蕉球将小足球射入球门。

还记得上面我们提过QPropertyAnimation()的setKeyValueAt()这个用于设置动画关键帧的方法。现在我们就将利用它来实现足球射门时的曲线。

与上面的图形界面的代码不一样的是,我们需要绘制一条曲线线条来作为足球射门时的路径。所以我们需要对上面的图形界面的代码进行一些修改:

# coding:utf-8
from PyQt5 import QtGui,QtWidgets,QtCore
import sysclass MainUi(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("动画使用-州的先生zmister.com") # 设置窗口标题self.resize(400,200) # 规定窗口大小self.main_widget = QtWidgets.QWidget() # 创建一个widget部件self.button = QtWidgets.QPushButton('射门',self.main_widget) # 创建一个按钮self.button.setGeometry(10,10,60,30) # 设置按钮位置self.label = QtWidgets.QLabel(self.main_widget) # 创建一个文本标签部件用于显示足球self.label.setGeometry(50,150,50,50) # 设置足球位置png = QtGui.QPixmap()  # 创建一个绘图类png.load("football.png")  # 从png中加载一个图片self.label.setPixmap(png)  # 设置文本标签的图形self.label.setScaledContents(True) # 图片随文本部件的大小变动self.qiumen = QtWidgets.QLabel(self.main_widget)  # 创建一个文本标签部件用于显示球门self.qiumen.setGeometry(345, 75, 50, 50)  # 设置球门位置pngqiumen = QtGui.QPixmap()  # 创建一个绘图类pngqiumen.load("qiumen.png")  # 从png中加载一个图片self.qiumen.setPixmap(pngqiumen)  # 设置文本标签的图形self.path = QtGui.QPainterPath() # 实例化一个绘制类,用于绘制动作self.path.moveTo(50, 150)self.path.cubicTo(50, 150, 50, 20, 370, 90)self.setCentralWidget(self.main_widget)# 重写patintEvent()方法def paintEvent(self, e):qp = QtGui.QPainter()qp.begin(self)qp.drawPath(self.path) # 在图形界面上根据self.path绘制一条线条qp.end()if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)gui = MainUi()gui.show()sys.exit(app.exec_())

在上面的代码中,与之前的程序代码有一下不同之处:

我们实例化创建了一个QtGui.QPainterPath(),用于进行绘制操作。通过它的moveTo()方法,设置了绘制的起始点,通过它的cubicTo()方法,设置的绘制的整个路径:

self.path = QtGui.QPainterPath() # 实例化一个绘制类,用于绘制动作
self.path.moveTo(50, 150)
self.path.cubicTo(50, 150, 50, 20, 370, 90)

接着,我们重写了窗口的paintEvent()方法,根据绘制操作的定义,在图形上绘制一条相应的线条:

def paintEvent(self, e):qp = QtGui.QPainter()qp.begin(self)qp.drawPath(self.path) # 在图形界面上根据self.path绘制一条线条qp.end()

这样,我们的图形界面程序呈现出来的就是如下图所示的样子:

 

 

图形上呈现了我们设置的足球将要运动的轨迹,接下来,我们通过QPropertyAnimation()的setKeyValueAt()设置关键帧的路径,来实现足球曲线射门,具体操作同样在shoot()方法中进行:

def shoot(self):self.anim_x = QtCore.QPropertyAnimation(self.label, b'geometry')                    self.anim_x.setDuration(3000)self.anim_x.setStartValue(QtCore.QRect(50,150,50,50)) # 设置动画对象的起始属性positionValues = [n / 10  for n in range(0, 10)]for n,i in enumerate(positionValues):x = self.path.pointAtPercent(i).x()y = self.path.pointAtPercent(i).y()z =  50 - n*3.5self.anim_x.setKeyValueAt(i,QtCore.QRect(x, y,z,z))self.anim_x.setEndValue(QtCore.QRect(360, 90, 10, 10))self.anim_x.start()

最后,同样将“射门”按钮的点击信号绑定在shoot()方法上。运行程序代码,点击“射门”按钮,将会出现如下动图所示的动画效果:

 

 

为了更加的美观,其实可以将重写的paintEvent()去掉,在这里为了演示路径,就没有去除。

在PyQt5中使用动画是不是很简单?有问题欢迎留言讨论。

这篇关于Python玩个球,如何用PyQt5实现足球射门动画?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/548547

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Python安装Pandas库的两种方法

《Python安装Pandas库的两种方法》本文介绍了三种安装PythonPandas库的方法,通过cmd命令行安装并解决版本冲突,手动下载whl文件安装,更换国内镜像源加速下载,最后建议用pipli... 目录方法一:cmd命令行执行pip install pandas方法二:找到pandas下载库,然后

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

Python操作PDF文档的主流库使用指南

《Python操作PDF文档的主流库使用指南》PDF因其跨平台、格式固定的特性成为文档交换的标准,然而,由于其复杂的内部结构,程序化操作PDF一直是个挑战,本文主要为大家整理了Python操作PD... 目录一、 基础操作1.PyPDF2 (及其继任者 pypdf)2.PyMuPDF / fitz3.Fre