【发布时间】:2021-05-09 20:42:35
【问题描述】:
我正在将 PyQt 5 用于 GUI 应用程序,但我遇到了线程问题。
有一个关闭按钮,一旦按下它,QTimer 就会启动,然后它会在一个 while 循环中等待,该循环取决于 QTimer 处理程序中正在递增的变量的值。
问题是计时器没有启动。有趣的是,如果我对 while 循环进行注释,则计时器可以正常工作。
代码如下:
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QHBoxLayout
import sys
import time
class MyClass(QMainWindow):
myTimer = None
myCounter = 0
def __init__(self):
QMainWindow.__init__(self)
myButton = QPushButton(text='Close')
myButton.clicked.connect(self.myButtonClicked)
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
ly = QHBoxLayout()
ly.addWidget(myButton)
centralWidget.setLayout(ly)
self.myTimer = QTimer()
self.myTimer .timeout.connect(self.__myTimerHandler)
def myButtonClicked(self):
self.myCounter= 0
self.myTimer.start(1000)
print('Loop Start')
while self.myCounter < 10:
self.__DoNothing()
print('Loop END')
def __DoNothing(self):
print('Nothing')
#time.sleep(2)
def __myTimerHandler(self):
self.myCounter = self.myCounter + 1
print('Counter:' + str(self.myCounter))
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWin = MyClass()
mainWin.show()
sys.exit( app.exec_() )
输出:
Loop Start
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
正如我所解释的,使用此代码 QTImer(我的计时器)不会启动。但是,如果我注释 while 循环,QTimer 会正确启动,并且每秒都会调用一次处理程序。
注释掉 DoNothing 函数中的 time.sleep 行没有帮助。
我可以想象这是关于多线程和访问同一个变量的问题,但我不知道如何解决它。
【问题讨论】:
-
在 Qt 主线程中永远不应发生阻塞函数或循环:您的计时器已启动,但由于 Qt 事件循环在
while中被阻塞,因此无法处理它.只需检查__myTimerHandler中的变量即可。 -
@musicamante 谢谢你的评论,现在我明白这是问题所在,但这样做的想法是等待调用处理程序的一定数量的重复,然后做其他事情,例如,在关闭窗口之前有一个从 20 到 0 的倒计时数。然后关闭窗口。
-
我不明白问题出在哪里:你已经让计数器工作了,如果你想让它重复 20 次然后停止(或做其他事情),只需添加一个
if self.myCounter >= 20: ... -
这就是我想说的,按照您建议的方式,我必须在 __myTimerHandler 中编写 if 条件行,但是我想在 myButtonClicked 函数中执行此操作。此实现的另一个好处是您可以将此计时器用作多个功能中的延迟。例如,如果你想在两行代码之间有一定的时间延迟。
-
@Majidkhalili 将
QApplication.processEvents()放入您的while 循环中,将time.sleep(1)放入__DoNothing。这将允许在运行否则会阻塞事件循环的代码时处理计时器事件。
标签: python pyqt pyqt5 qthread qtimer