[英]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()
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.