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

103 阅读8分钟

 

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

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

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

# coding:utf-8

from PyQt5 import QtGui,QtWidgets,QtCore
import sys

class 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_widget
        self.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 sys

class 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 sys

class 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 sys

class 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_())

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

了解详情:docs.qq.com/doc/DSnl3ZG…