1. 程式人生 > >《快速掌握PyQt》 第十章 定時器QTimer和進度條QProgressBar

《快速掌握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