python - PYQT QTimer 不启动
问题描述
我正在将 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 行没有帮助。
我可以想象这是关于多线程和访问同一个变量的事情,但我不知道如何解决它。
解决方案
正如@musicamante 在评论中提到的“在主 Qt 线程中不应发生阻塞函数或循环”。在问题中提供的代码中,线程实际上正在启动,但是由于阻塞循环,处理程序没有被调用的机会。
正如评论中提到的@ekhumoro,解决方案是使用“QApplication.processEvents()”处理等待循环中的事件。并且还在“__DoNothing”函数中添加了一个睡眠函数。
所以最终的解决方案如下:
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()
QApplication.processEvents()
print('Loop END')
def __DoNothing(self):
print('Nothing')
time.sleep(0.250)
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
Counter:1
Nothing
Nothing
Nothing
Nothing
Counter:2
Nothing
Nothing
Nothing
Nothing
Counter:3
Nothing
Nothing
Nothing
Loop Start
Nothing
Nothing
Nothing
Nothing
Counter:1
Nothing
Nothing
Nothing
Nothing
Counter:2
Nothing
Nothing
Nothing
Nothing
Nothing
Counter:3
Nothing
Nothing
Nothing
Counter:4
Nothing
Nothing
Nothing
Nothing
Counter:5
Nothing
Nothing
Nothing
Nothing
Counter:6
Nothing
Nothing
Nothing
Nothing
Counter:7
Nothing
Nothing
Nothing
Nothing
Counter:8
Nothing
Nothing
Nothing
Nothing
Counter:9
Nothing
Nothing
Nothing
Nothing
Counter:10
Loop END
Loop END
显然两个计数器回调的时间差不一定相同。
推荐阅读
- c++ - C ++以其他方式增加指针
- jquery - Rails 使用 jQuery 重定向到带有参数的 url
- c - 打印二维矩阵?
- jenkins - 詹金斯管道sh不适用于少数命令
- entity-framework-core - EF Core 非原始类型值对象作为主键?
- macos - 复制文件名的前六个字符并将其修改为相同 .txt 文件的顶行
- python - tkinter 返回动态复选框的名称
- java - 具有十六进制长数组的 CRC16 数据类型 java
- google-chrome - 我可以检测触摸键盘当前是否已部署并请求它吗?
- enterprise-architect - 如何在 Enterprise Architect 部署模型中对可重用的计算机配置进行建模