摘要:作為一個(gè)全面的桌面應(yīng)用程序開(kāi)發(fā)包,其自然提供了對(duì)圖像的動(dòng)畫支持。本篇文章中,就來(lái)簡(jiǎn)單地在中使用動(dòng)畫功能實(shí)現(xiàn)一個(gè)足球射門的動(dòng)畫效果。還記得上面我們提過(guò)的這個(gè)用于設(shè)置動(dòng)畫關(guān)鍵幀的方法。在中使用動(dòng)畫是不是很簡(jiǎn)單有問(wèn)題歡迎留言討論。
QT作為一個(gè)全面的桌面應(yīng)用程序開(kāi)發(fā)包,其自然提供了對(duì)圖像的動(dòng)畫支持。本篇文章中,就來(lái)簡(jiǎn)單地在PYQt5中使用Animation動(dòng)畫功能實(shí)現(xiàn)一個(gè)足球射門的動(dòng)畫效果。
本篇將會(huì)依次完成以下功能:
在GUI界面中顯示一個(gè)圖片(用一個(gè)足球做演示);
點(diǎn)擊按鈕實(shí)現(xiàn)足球的直線射門動(dòng)畫;
點(diǎn)擊按鈕實(shí)現(xiàn)足球的曲線射門動(dòng)畫;
本文首發(fā)州的先生博客:Python GUI教程(十五):在PyQt5中使用動(dòng)畫,轉(zhuǎn)載請(qǐng)注明出處一、在圖形界面顯示圖片的兩種方法
一般情況下,想要在GUI中顯示圖片,我們會(huì)通過(guò):
實(shí)例化一個(gè)QLable()部件;
實(shí)例化一個(gè)QPixmap()圖形類;
通過(guò)QLabel()部件的setPixmap()方法設(shè)置QLabel()部件的圖形;
就像如下代碼所示:
# coding:utf-8 from PyQt5 import QtGui,QtWidgets import sys class MainUi(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("動(dòng)畫使用-zmister.com") # 設(shè)置窗口標(biāo)題 self.resize(400,200) # 規(guī)定窗口大小 self.main_widget = QtWidgets.QWidget() # 創(chuàng)建一個(gè)widget部件 self.label = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件 png = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 png.load("logo.png") # 從pngz中加載一個(gè)圖片 self.label.setPixmap(png) # 設(shè)置文本標(biāo)簽的圖形 self.setCentralWidget(self.main_widget) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) gui = MainUi() gui.show() sys.exit(app.exec_())
運(yùn)行上述代碼,我們將會(huì)得到如下所示的圖形界面:
但是這種方法沒(méi)有辦法實(shí)現(xiàn)對(duì)圖片更多的控制。為了更好地對(duì)圖形界面中的圖片進(jìn)行控制和管理,我們還需要使用到其他的類,比如QtWidgets中的QGraphicsScene類,QGraphicsScene提供了一個(gè)場(chǎng)景,用于對(duì)2D圖形進(jìn)行管理。同時(shí),為了展示QGraphicsScene中的內(nèi)容,我們還需要使用到QtWidgets中的QGraphicsView類來(lái)提供一個(gè)視圖部件。
下面,我們就通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)了解一下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("動(dòng)畫使用-zmister.com") # 設(shè)置窗口標(biāo)題 self.resize(400,200) # 規(guī)定窗口大小 self.main_widget = QtWidgets.QWidget() # 創(chuàng)建一個(gè)widget部件 self.grapview = QtWidgets.QGraphicsView(self.main_widget) # 創(chuàng)建一個(gè)圖形視圖,繼承自main_widget self.grapview.setGeometry(QtCore.QRect(10, 10, 380, 180)) # 設(shè)置圖形視圖的矩形區(qū)域 self.scene = QtWidgets.QGraphicsScene() # 創(chuàng)建一個(gè)圖形管理場(chǎng)景 self.grapview.setScene(self.scene) png = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 png.load("logo.png") # 從png中加載一個(gè)圖片 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_())
在這里面,基礎(chǔ)的窗口代碼與之前的代碼類似,有區(qū)別且最核心的為以下幾行代碼。
首先,我們實(shí)例化創(chuàng)建了一個(gè)用于展示圖形場(chǎng)景的圖形視圖QGraphicsView(),將它繼承自self.main_widget主窗口部件:
self.grapview = QtWidgets.QGraphicsView(self.main_widget)
然后,我們實(shí)例化創(chuàng)建了一個(gè)圖形場(chǎng)景管理類QGraphicsScene(),并通過(guò)setScene()方法將圖形視圖self.grapview的圖形場(chǎng)景設(shè)置為剛剛實(shí)例化創(chuàng)建的QGraphicsScene():
self.scene = QtWidgets.QGraphicsScene() self.grapview.setScene(self.scene)
最后,我們通過(guò)QPixmap()創(chuàng)建并加載了一個(gè)圖片,將其添加到圖形項(xiàng)目QGraphicsPixmapItem()中,并通過(guò)addItem()方法將圖形項(xiàng)目添加到圖形場(chǎng)景管理self.scene中:
png = QtGui.QPixmap() png.load("logo.png") item = QtWidgets.QGraphicsPixmapItem(png) self.scene.addItem(item)
如此,我們就完成了通過(guò)QGraphicsView()類和QGraphicsScene()類在圖形界面(GUI)中展示圖片的功能,運(yùn)行完整的代碼,其顯示出來(lái)的圖形界面程序如下圖所示:
二、幾行代碼射個(gè)門上面我們通過(guò)兩種不同的方式實(shí)現(xiàn)了圖片在圖形界面中的展示,接下來(lái),我們借助QtCore中的QPropertyAnimation()來(lái)實(shí)現(xiàn)圖片的動(dòng)畫效果。
QPropertyAnimation()類主要依靠操縱對(duì)象的QT屬性來(lái)實(shí)現(xiàn)動(dòng)畫效果,其有幾個(gè)比較主要的方法:
start():用于啟動(dòng)動(dòng)畫;
stop():用于停止動(dòng)畫;
setStartValue():用于設(shè)置動(dòng)畫的起始值;
setEndValue():用于設(shè)置動(dòng)畫的結(jié)束值;
setDuration():用于設(shè)置動(dòng)畫的持續(xù)時(shí)間;
setKeyValueAt():用于在特定時(shí)間創(chuàng)建一個(gè)關(guān)鍵的動(dòng)畫幀動(dòng)作;
setLoopCount():用于設(shè)置動(dòng)畫的循環(huán)次數(shù);
下面我們就使用QPropertyAnimation()類實(shí)現(xiàn)圖片的動(dòng)畫。為了動(dòng)畫的效果比5毛特效要好一點(diǎn),州的先生(公眾號(hào):zmister2016)在阿里的圖標(biāo)庫(kù)iconfont里找了一個(gè)小足球和球門的圖標(biāo),嗯,就像這樣:
然后,我們創(chuàng)建一個(gè)圖形界面,里面包含一個(gè)按鈕、一個(gè)小球和一個(gè)球門的圖片:
# 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("動(dòng)畫使用-zmister.com") # 設(shè)置窗口標(biāo)題 self.resize(400,200) # 規(guī)定窗口大小 self.main_widget = QtWidgets.QWidget() # 創(chuàng)建一個(gè)widget部件 self.button = QtWidgets.QPushButton("射門",self.main_widget) # 創(chuàng)建一個(gè)按鈕 self.button.setGeometry(10,10,60,30) # 設(shè)置按鈕位置 self.label = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件用于顯示足球 self.label.setGeometry(50,80,50,50) # 設(shè)置足球位置 png = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 png.load("football.png") # 從png中加載一個(gè)圖片 self.label.setPixmap(png) # 設(shè)置文本標(biāo)簽的圖形 self.label.setScaledContents(True) self.qiumen = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件用于顯示球門 self.qiumen.setGeometry(345, 75, 50, 50) # 設(shè)置球門位置 pngqiumen = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 pngqiumen.load("qiumen.png") # 從png中加載一個(gè)圖片 self.qiumen.setPixmap(pngqiumen) # 設(shè)置文本標(biāo)簽的圖形 self.setCentralWidget(self.main_widget) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) gui = MainUi() gui.show() sys.exit(app.exec_())
運(yùn)行上述代碼,我們會(huì)得到一個(gè)如下圖所示的圖形界面:
我們的目的是想讓圖形界面中的小足球通過(guò)按鈕控制,進(jìn)入到球門中。接下來(lái),我們就通過(guò)QPropertyAnimation()類來(lái)實(shí)現(xiàn)這個(gè)效果。
在MainUi()中新建一個(gè)名為shoot()的方法,在其中寫入以下代碼:
self.anim = QtCore.QPropertyAnimation(self.label,b"geometry") # 設(shè)置動(dòng)畫的對(duì)象及其屬性 self.anim.setDuration(2000) # 設(shè)置動(dòng)畫間隔時(shí)間 self.anim.setStartValue(QtCore.QRect(50,80,50,50)) # 設(shè)置動(dòng)畫對(duì)象的起始屬性 self.anim.setEndValue(QtCore.QRect(360, 90, 10, 10)) # 設(shè)置動(dòng)畫對(duì)象的結(jié)束屬性 self.anim.start() # 啟動(dòng)動(dòng)畫
最后,我們?cè)僦v按鈕的點(diǎn)擊信號(hào)綁定到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("動(dòng)畫使用-zmister.com") # 設(shè)置窗口標(biāo)題 self.resize(400,200) # 規(guī)定窗口大小 self.main_widget = QtWidgets.QWidget() # 創(chuàng)建一個(gè)widget部件 self.button = QtWidgets.QPushButton("射門",self.main_widget) # 創(chuàng)建一個(gè)按鈕 self.button.setGeometry(10,10,60,30) # 設(shè)置按鈕位置 self.button.clicked.connect(self.shoot) self.label = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件用于顯示足球 self.label.setGeometry(50,80,50,50) # 設(shè)置足球位置 png = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 png.load("football.png") # 從png中加載一個(gè)圖片 self.label.setPixmap(png) # 設(shè)置文本標(biāo)簽的圖形 self.label.setScaledContents(True) # 圖片隨文本部件的大小變動(dòng) self.qiumen = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件用于顯示球門 self.qiumen.setGeometry(345, 75, 50, 50) # 設(shè)置球門位置 pngqiumen = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 pngqiumen.load("qiumen.png") # 從png中加載一個(gè)圖片 self.qiumen.setPixmap(pngqiumen) # 設(shè)置文本標(biāo)簽的圖形 self.setCentralWidget(self.main_widget) def shoot(self): self.anim = QtCore.QPropertyAnimation(self.label,b"geometry") # 設(shè)置動(dòng)畫的對(duì)象及其屬性 self.anim.setDuration(2000) # 設(shè)置動(dòng)畫間隔時(shí)間 self.anim.setStartValue(QtCore.QRect(50,80,50,50)) # 設(shè)置動(dòng)畫對(duì)象的起始屬性 self.anim.setEndValue(QtCore.QRect(360, 90, 10, 10)) # 設(shè)置動(dòng)畫對(duì)象的結(jié)束屬性 self.anim.start() # 啟動(dòng)動(dòng)畫 if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) gui = MainUi() gui.show() sys.exit(app.exec_())
運(yùn)行上述代碼,點(diǎn)擊“射門”按鈕,我們將會(huì)得到如下動(dòng)圖所示的動(dòng)畫:
這樣,通過(guò)QPropertyAnimation()的setDuration()方法、setStartValue()方法、setEndValue()方法我們就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的動(dòng)畫。
三、圓月彎刀繼續(xù)射門但是上面的射門動(dòng)畫是一條直線將小足球移動(dòng)到了球門之內(nèi),簡(jiǎn)單粗暴欠缺了些許美感,下面,我們讓這個(gè)射門換一種方式,用圓月彎刀的香蕉球?qū)⑿∽闱蛏淙肭蜷T。
還記得上面我們提過(guò)QPropertyAnimation()的setKeyValueAt()這個(gè)用于設(shè)置動(dòng)畫關(guān)鍵幀的方法?,F(xiàn)在我們就將利用它來(lái)實(shí)現(xiàn)足球射門時(shí)的曲線。
與上面的圖形界面的代碼不一樣的是,我們需要繪制一條曲線線條來(lái)作為足球射門時(shí)的路徑。所以我們需要對(duì)上面的圖形界面的代碼進(jìn)行一些修改:
# 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("動(dòng)畫使用-州的先生zmister.com") # 設(shè)置窗口標(biāo)題 self.resize(400,200) # 規(guī)定窗口大小 self.main_widget = QtWidgets.QWidget() # 創(chuàng)建一個(gè)widget部件 self.button = QtWidgets.QPushButton("射門",self.main_widget) # 創(chuàng)建一個(gè)按鈕 self.button.setGeometry(10,10,60,30) # 設(shè)置按鈕位置 self.label = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件用于顯示足球 self.label.setGeometry(50,150,50,50) # 設(shè)置足球位置 png = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 png.load("football.png") # 從png中加載一個(gè)圖片 self.label.setPixmap(png) # 設(shè)置文本標(biāo)簽的圖形 self.label.setScaledContents(True) # 圖片隨文本部件的大小變動(dòng) self.qiumen = QtWidgets.QLabel(self.main_widget) # 創(chuàng)建一個(gè)文本標(biāo)簽部件用于顯示球門 self.qiumen.setGeometry(345, 75, 50, 50) # 設(shè)置球門位置 pngqiumen = QtGui.QPixmap() # 創(chuàng)建一個(gè)繪圖類 pngqiumen.load("qiumen.png") # 從png中加載一個(gè)圖片 self.qiumen.setPixmap(pngqiumen) # 設(shè)置文本標(biāo)簽的圖形 self.path = QtGui.QPainterPath() # 實(shí)例化一個(gè)繪制類,用于繪制動(dòng)作 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) # 在圖形界面上根據(jù)self.path繪制一條線條 qp.end() if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) gui = MainUi() gui.show() sys.exit(app.exec_())
在上面的代碼中,與之前的程序代碼有一下不同之處:
我們實(shí)例化創(chuàng)建了一個(gè)QtGui.QPainterPath(),用于進(jìn)行繪制操作。通過(guò)它的moveTo()方法,設(shè)置了繪制的起始點(diǎn),通過(guò)它的cubicTo()方法,設(shè)置的繪制的整個(gè)路徑:
self.path = QtGui.QPainterPath() # 實(shí)例化一個(gè)繪制類,用于繪制動(dòng)作 self.path.moveTo(50, 150) self.path.cubicTo(50, 150, 50, 20, 370, 90)
接著,我們重寫了窗口的paintEvent()方法,根據(jù)繪制操作的定義,在圖形上繪制一條相應(yīng)的線條:
def paintEvent(self, e): qp = QtGui.QPainter() qp.begin(self) qp.drawPath(self.path) # 在圖形界面上根據(jù)self.path繪制一條線條 qp.end()
這樣,我們的圖形界面程序呈現(xiàn)出來(lái)的就是如下圖所示的樣子:
圖形上呈現(xiàn)了我們?cè)O(shè)置的足球?qū)⒁\(yùn)動(dòng)的軌跡,接下來(lái),我們通過(guò)QPropertyAnimation()的setKeyValueAt()設(shè)置關(guān)鍵幀的路徑,來(lái)實(shí)現(xiàn)足球曲線射門,具體操作同樣在shoot()方法中進(jìn)行:
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)) # 設(shè)置動(dòng)畫對(duì)象的起始屬性 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.5 self.anim_x.setKeyValueAt(i,QtCore.QRect(x, y,z,z)) self.anim_x.setEndValue(QtCore.QRect(360, 90, 10, 10)) self.anim_x.start()
最后,同樣將“射門”按鈕的點(diǎn)擊信號(hào)綁定在shoot()方法上。運(yùn)行程序代碼,點(diǎn)擊“射門”按鈕,將會(huì)出現(xiàn)如下動(dòng)圖所示的動(dòng)畫效果:
為了更加的美觀,其實(shí)可以將重寫的paintEvent()去掉,在這里為了演示路徑,就沒(méi)有去除。
在PyQt5中使用動(dòng)畫是不是很簡(jiǎn)單?有問(wèn)題歡迎留言討論。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42287.html
摘要:世界杯小組賽將收官,你還依然信嗎冷門頻出,黑馬擊敗豪強(qiáng)。以本屆世界杯開(kāi)幕戰(zhàn)俄羅斯對(duì)陣沙特阿拉伯的比賽為例,兩隊(duì)上次交手是在年的一場(chǎng)友誼賽,距今已經(jīng)年。然后進(jìn)入第二步,預(yù)測(cè)回報(bào)率導(dǎo)向。在足球領(lǐng)域,這個(gè)回報(bào)率已非常不俗。 世界杯小組賽將收官,你還依然信AI嗎?冷門頻出,黑馬擊敗豪強(qiáng)。不少AI模型始料未及。到底還能不能愉快找到科學(xué)規(guī)律?或者說(shuō)足球比賽乃至其他競(jìng)技體育賽事,數(shù)據(jù)科學(xué)家在AI加持下,究...
摘要:也就是說(shuō),這個(gè)機(jī)器學(xué)習(xí)模型,現(xiàn)在還只能當(dāng)做一種參考,還不能將場(chǎng)外號(hào)召力也計(jì)入工資體系中。不過(guò)研究者稱,無(wú)論是足球迷還是非足球迷,這個(gè)機(jī)器學(xué)習(xí)模型,都能為未來(lái)商品定價(jià)提供參考。 內(nèi)馬爾2.2億歐元轉(zhuǎn)換大巴黎阿森納主帥溫格在位20載,什么樣優(yōu)秀的球員沒(méi)見(jiàn)過(guò),但現(xiàn)今他也是越來(lái)越看不懂轉(zhuǎn)會(huì)市場(chǎng)了。溫格感嘆:不是阿森納不買人,實(shí)在是現(xiàn)今市場(chǎng)上的球員貴得離譜。此言其實(shí)不虛。120萬(wàn)英鎊的坎通納幫助弗格森...
摘要:這個(gè)周末舉行的俄羅斯世界杯決賽可謂精彩紛呈,高盧雄雞和潘帕斯雄鷹上演進(jìn)球大戰(zhàn),姆巴佩一人獨(dú)造三粒進(jìn)球一戰(zhàn)成名,法國(guó)隊(duì)比送阿根廷回家,梅西再度飲恨而歸,另一邊葡萄牙比不敵烏拉圭,梅西與羅兩大超巨止步八強(qiáng)。 摘要: 這個(gè)周末舉行的俄羅斯世界杯1/8決賽可謂精彩紛呈,高盧雄雞和潘帕斯雄鷹上演進(jìn)球大戰(zhàn),姆巴佩一人獨(dú)造三粒進(jìn)球一戰(zhàn)成名,法國(guó)隊(duì)4比3送阿根廷回家,梅西再度飲恨而歸,另一邊葡萄牙1比...
閱讀 1765·2021-09-27 14:02
閱讀 3180·2021-09-27 13:36
閱讀 1056·2019-08-30 12:46
閱讀 1843·2019-08-30 10:51
閱讀 3583·2019-08-29 17:02
閱讀 955·2019-08-29 16:38
閱讀 1856·2019-08-29 16:37
閱讀 3033·2019-08-26 10:32