簡體   English   中英

PyQt5 使用 Loop 更改標簽文本

[英]PyQt5 chang Label text using Loop

代碼它沒有錯誤但是當運行程序時會凍結程序它的倒計時使用按鈕開始倒計時下圖描述布局在此處輸入圖像描述

問題是我正在使用循環來更改標簽文本並使程序凍結

from time import sleep
import PyQt5.QtWidgets as Qtw


class MainWindow(Qtw.QWidget):

    def __init__(self):
        super().__init__()

        self.setLayout(Qtw.QVBoxLayout())
        
        pushButton = Qtw.QPushButton("start",clicked = lambda: setting_label())
        self.layout().addWidget(pushButton)


        my_label = Qtw.QLabel("00:00:00")
        self.layout().addWidget(my_label)
        

        self.show()
        def setting_label():
            t = 1200
            while t:
            
                h  = t // 3600
                m  = t // 60
                s  = t % 60
                timer = "{:02d}:{:02d}:{:02d}".format(h,m,s)
                my_label.setText(timer)
                sleep(1)
                t -= 1


   

app = Qtw.QApplication([])
window = MainWindow()
    
app.exec_()

代碼在 OP 中的編寫方式並沒有真正卡住或凍結。 而是顯示無法更新。 您可以通過嘗試強制 Qt 使用app.processEvents()更新 GUI 來解決此問題。 將它放在 setText() 之后的setting_label函數中:

self.my_label.setText(timer)
app.processEvents()

首選方式

通常不鼓勵大量使用app.processEvents() 制作倒數計時器的另一種方法是使用QTimer 設置所有信號和時隙需要更多開銷。 但它可能非常強大。 這是一個例子

from time import sleep
import PyQt5.QtWidgets as Qtw
from PyQt5.QtCore import QTimer

class MainWindow(Qtw.QWidget):

    def __init__(self):
        super().__init__()

        self.setLayout(Qtw.QVBoxLayout())

        pushButton = Qtw.QPushButton("start",clicked = self.start_countdown)
        self.layout().addWidget(pushButton)

        self.my_label = Qtw.QLabel("00:00:00")
        self.layout().addWidget(self.my_label)

        self.timer = QTimer()        # create a new QTimer instance
        self.timer.setInterval(1000) # make it fire every 1000 msec
        self.t = 1200
        self.timer.timeout.connect(self.setting_label) # connect the timeout signal to self.setting_label

        self.show()

    def start_countdown(self):
        self.t = 1200
        self.timer.start()

    def setting_label(self):

        if self.t == 0:
            self.timer.stop()
            print('timer stopped')

        h  = self.t // 3600
        m  = self.t // 60
        s  = self.t % 60
        timer = "{:02d}:{:02d}:{:02d}".format(h,m,s)
        self.my_label.setText(timer)
        self.t -= 1

app = Qtw.QApplication([])
window = MainWindow()

app.exec_()

編輯:此解決方案適用於 OP,但其他人指出,使用threading執行此操作會導致意外行為、崩潰等,因此最好使用其他方法執行此操作(例如: this answer

界面凍結是因為您用於更改標簽的 while 循環阻塞了應用程序的事件循環(即接收輸入)。 您可以通過將函數移動到這樣的線程來解決此問題:

import threading
from time import sleep

import PyQt5.QtWidgets as Qtw


class MainWindow(Qtw.QWidget):
    def __init__(self):
        super().__init__()

        self.setLayout(Qtw.QVBoxLayout())

        def setting_label():
            t = 1200
            while t:
                h  = t // 3600
                m  = t // 60
                s  = t % 60
                timer = "{:02d}:{:02d}:{:02d}".format(h,m,s)
                my_label.setText(timer)
                sleep(1)
                t -= 1
        
        pushButton = Qtw.QPushButton(
            "start",
            clicked=lambda: thread.Thread(target=setting_label).start()
        )
        self.layout().addWidget(pushButton)

        my_label = Qtw.QLabel("00:00:00")
        self.layout().addWidget(my_label)

        self.show()


app = Qtw.QApplication([])
window = MainWindow()
    
app.exec_()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM