简体   繁体   English

PyQt5 使用 Loop 更改标签文本

[英]PyQt5 chang Label text using Loop

code it's clean from bugs but when is running program will freezing the program its countdown using button to start the countdown the picture below discripe the layout enter image description here代码它没有错误但是当运行程序时会冻结程序它的倒计时使用按钮开始倒计时下图描述布局在此处输入图像描述

the probelm is im using loop to changing label text and that make program freezed问题是我正在使用循环来更改标签文本并使程序冻结

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

The way the code is written in the OP, it doesn't really get stuck or frozen.代码在 OP 中的编写方式并没有真正卡住或冻结。 But rather, the display fails to update.而是显示无法更新。 You can get around this by trying to force Qt to update the GUI with app.processEvents() .您可以通过尝试强制 Qt 使用app.processEvents()更新 GUI 来解决此问题。 Put it in your setting_label function after the setText():将它放在 setText() 之后的setting_label函数中:

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

The Preferred Way首选方式

Using app.processEvents() a lot is usually discouraged.通常不鼓励大量使用app.processEvents() Another way to make a countdown timer is to use a QTimer .制作倒数计时器的另一种方法是使用QTimer There is a little more overhead in setting up all of the signals and slots.设置所有信号和时隙需要更多开销。 But it can be very powerful.但它可能非常强大。 Here is an example这是一个例子

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

Edit: This solution works for the OP, but others have pointed out that doing this using threading can cause unexpected behavior, crashes, etc. so it's better to do this using other methods (for example: this answer )编辑:此解决方案适用于 OP,但其他人指出,使用threading执行此操作会导致意外行为、崩溃等,因此最好使用其他方法执行此操作(例如: this answer

The interface freezes because the while loop you use to change the label blocks the event loop of the app (ie receiving inputs).界面冻结是因为您用于更改标签的 while 循环阻塞了应用程序的事件循环(即接收输入)。 You can fix this by moving the function to a thread like this:您可以通过将函数移动到这样的线程来解决此问题:

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