《快速掌握PyQt》 第十章 定時器QTimer和進度條QProgressBar
第十章 定時器QTimer和進度條QProgressBar
當我們要讓程式定期去執行某函式的時候,QTimer就派上用場了,比如一個遊戲程式,它通常會定期去呼叫一個函式來進行更新操作。而進度條可以用來顯示某項任務的進度,從而讓使用者介面更加友好。
我們通常將將QTimer和QProgressBar一起搭配使用,所以本章就一起介紹了。
10.1 QTimer
以下這個程式中,按鈕被點選後,QLabel顯示的數字會不斷增加:
import sys from PyQt5.QtCore import QTimer, Qt from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.label = QLabel('0', self) # 1 self.label.setAlignment(Qt.AlignCenter) self.step = 0 # 2 self.timer = QTimer(self) # 3 self.timer.timeout.connect(self.update_func) self.ss_button = QPushButton('Start', self) # 4 self.ss_button.clicked.connect(self.start_stop_func) self.v_layout = QVBoxLayout() self.v_layout.addWidget(self.label) self.v_layout.addWidget(self.ss_button) self.setLayout(self.v_layout) def start_stop_func(self): if not self.timer.isActive(): self.ss_button.setText('Stop') self.timer.start(100) else: self.ss_button.setText('Start') self.timer.stop() def update_func(self): self.step += 1 self.label.setText(str(self.step)) if __name__ == '__main__': app = QApplication(sys.argv) demo = Demo() demo.show() sys.exit(app.exec_())
1. 首先例項化一個QLabel,並將文字設為0。setAlignment(Qt.AlignCenter)可以讓QLabel控制元件在視窗中居中顯示,而之前我們是通過addStretch(int)方法來讓一個控制元件在佈局中居中的,顯然通過setAlignment(Qt.AlignCenter)方法更加方便:
self.h_layout.addStretch(1)
self.h_layout.addWidget(self.label)
self.h_layout.addStretch(1)
2. step變數用於計數,QLabel控制元件顯示的就是這裡的step,程式會通過QTimer來不斷增加step的值;
3. 其次例項化一個QTimer,並將timeout訊號連線到自定義的槽函式update_func()上:
def update_func(self):
self.step += 1
self.label.setText(str(self.step))
每次呼叫該槽函式就會將step值加1,並且用QLabel顯示當前值;
4. 最後我們例項化一個QPushButton按鈕來控制定時器的啟動的停止,連線的自定義的槽函式如下:
def start_stop_func(self): if not self.timer.isActive(): self.ss_button.setText('Stop') self.timer.start(100) else: self.ss_button.setText('Start') self.timer.stop()
在槽函式中通過isActive()方法來判斷定時器是否處於啟用狀態,若沒有啟用,則將按鈕文字變成Stop並通過start(100)方法來啟動定時器,100表示100毫秒,也就是說每過0.1秒,定時器就會觸發timeout訊號,並執行update_func()槽函式;若已經處於啟用狀態,則將按鈕文字變回Start並通過stop()方法停止定時器。
有些小夥伴可能想在觸發timeout訊號後只調用一次update_func(),那麼我們可以通過setSingleShot(True)方法來設定。
執行截圖如下:
10.2 QProgressBar
import sys
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QProgressBar, QPushButton, QHBoxLayout, QVBoxLayout
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.progressbar = QProgressBar(self) # 1
# self.progressbar.setOrientation(Qt.Vertical)
self.progressbar.setMinimum(0) # 2
self.progressbar.setMaximum(100)
# self.progressbar.setRange(0, 100)
self.step = 0 # 3
self.timer = QTimer(self) # 4
self.timer.timeout.connect(self.update_func)
self.ss_button = QPushButton('Start', self) # 5
self.ss_button.clicked.connect(self.start_stop_func)
self.reset_button = QPushButton('Reset', self) # 6
self.reset_button.clicked.connect(self.reset_func)
self.h_layout = QHBoxLayout()
self.v_layout = QVBoxLayout()
self.h_layout.addWidget(self.ss_button)
self.h_layout.addWidget(self.reset_button)
self.v_layout.addWidget(self.progressbar)
self.v_layout.addLayout(self.h_layout)
self.setLayout(self.v_layout)
def start_stop_func(self):
if self.ss_button.text() == 'Start':
self.ss_button.setText('Stop')
self.timer.start(100)
else:
self.ss_button.setText('Start')
self.timer.stop()
def update_func(self):
self.step += 1
self.progressbar.setValue(self.step)
if self.step >= 100:
self.ss_button.setText('Start')
self.timer.stop()
self.step = 0
def reset_func(self):
self.progressbar.reset()
self.ss_button.setText('Start')
self.timer.stop()
self.step = 0
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
1. 例項化一個QProgressBar,預設是水平的,但是我們可以通過setOrientation(Qt.Vertical)方法來讓進度條垂直顯示;
2. 通過setMinimum()和setMaximum()方法來設定範圍,也可以單單用setRange()方法來實現,這裡我們將範圍設為0-100;
3. 這裡的step變數用於計數,之後QProgressBar會將值設為step;
4. 例項化一個QTimer,並將timeout訊號連線到update_func()槽函式上:
def update_func(self):
self.step += 1
self.progressbar.setValue(self.step)
if self.step >= 100:
self.ss_button.setText('Start')
self.timer.stop()
self.step = 0
每次觸發timeout都會呼叫該槽函式,在這裡我們將step值加1,並將progressbar的值設為step,當step值達到pregress的最大值時(也就是說進度條達到100%),將按鈕文字重新設為Start,停止定時器並將step值重設為0;
5. 例項化一個QPushButton按鈕來控制QTimer的啟動與停止,這裡將它的clicked訊號和start_stop_func()槽函式連線起來:
def start_stop_func(self):
if self.ss_button.text() == 'Start':
self.ss_button.setText('Stop')
self.timer.start(100)
else:
self.ss_button.setText('Start')
self.timer.stop()
在槽函式中,我們通過按鈕文字來進行判斷,若為Start,則說明定時器沒有啟動,所以將按鈕文字設為Stop,並且通過start(100)方法來啟動,100表示100毫秒,即0.1秒。也就是說之後每隔0.1秒就會觸發timeout訊號並呼叫update_func()槽函式;若按鈕文字為Stop,則將其設為Start並停止定時器(我們在10.1章節中時通過定時器isActive()方法來的,當然這裡也可以使用);
6. 該例項化的按鈕用於重置進度條:
def reset_func(self):
self.progressbar.reset()
self.ss_button.setText('Start')
self.timer.stop()
self.step = 0
其所連線的槽函式中通過reset()方法來進行重置,還有將按鈕文字設為Start,停止定時器以及將step值設為0。
執行截圖如下:
10.3 小結
1. QTimer定時器會根據設定的時間不斷髮出timeout訊號並呼叫連線的槽函式,通過start(int)方法來設定時間並啟動定時器,stop()方法用於停止定時器;
2. 通過isActive()方法來判斷定時器是否被啟用,setSingleShot()方法可以在觸發timeout訊號後只調用一次槽函式;
3. 通過setOrientation(Qt.Vertical)方法可以將進度條設為垂直顯示;
4. setMinimum()和setMaximum()方法用來設定進度條範圍(可以用setRange()替代),setValue()方法用於設定進度條的當前值,reset()方法用於重置進度條。
bug記錄:不知道為什麼在Mac上QPushButton的文字改變有點問題,不知道有沒有小夥伴遇到的,請告知。
----------------------------------------------------------------------
喜歡的小夥伴可以加入這個Python QQ交流群一起學習:820934083