PYQT QTimer 没有启动

PYQT QTimer does not start

我正在将 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

显然两个计数器回调的时间差不一定相同