2013-02-22 78 views
2

我使用pyside,但(我认为)是一个通用的Qt问题。如何在使用QWaitCondition的QThread中使用QTimer? (pyside)

我知道QThread实现调用._exec()方法,所以我们应该在启动的QThread上有一个事件循环。通过这种方式,我们可以在该线程上使用QTimer(我已经完成了这个工作,它完美地工作)。我的问题是,当QWaitCondition也被使用时,我想有一个“消费者”线程,等待从QWaitCondition通知(来自生产者)的无限循环。我遇到的问题是,使用这种设计,我无法在消费者线程中使用QTimer。

这是该方案的一个片段,我试图解释:

from PySide import QtGui 
from PySide import QtCore 
import sys 

class MainWindow(QtGui.QMainWindow): 
    def __init__(self): 
     super(MainWindow, self).__init__() 

     self.button = QtGui.QPushButton(self) 
     self.button.setText("Periodical") 
     self.button.clicked.connect(self.periodical_call) 

     self.thread = QtCore.QThread() 
     self.worker = Worker() 
     self.worker.moveToThread(self.thread) 
     self.thread.started.connect(self.worker.loop) 
     self.thread.start() 

    def closeEvent(self, x): 
     self.worker.stop() 
     self.thread.quit() 
     self.thread.wait() 

    def periodical_call(self): 
     self.worker.do_stuff("main window") # this works 
     self.timer = QtCore.QTimer() 
     self.timer.timeout.connect(self.do_stuff) # this also works 
     self.timer.start(2000) 

    def do_stuff(self): 
     self.worker.do_stuff("timer main window") 

class Worker(QtCore.QObject): 
    def do_stuff_timer(self): 
     do_stuff("timer worker") 

    def do_stuff(self, origin): 
     self.origin = origin 
     self.wait.wakeOne() 

    def stop(self): 
     self._exit = True 
     self.wait.wakeAll() 

    def loop(self): 
     self.wait = QtCore.QWaitCondition() 
     self.mutex = QtCore.QMutex() 
     self._exit = False 
     while not self._exit: 
      self.wait.wait(self.mutex) 

      print "loop from %s" % (self.origin,) 

      self.timer = QtCore.QTimer() 
      self.timer.setSingleShot(True) 
      self.timer.timeout.connect(self.do_stuff_timer) 
      self.timer.start(1000) # <---- this doesn't work 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    frame = MainWindow() 
    frame.show() 
    sys.exit(app.exec_()) 

一旦你点击我们得到这样的输出按钮:

loop from main window      
loop from timer main window 
loop from timer main window 
loop from timer main window 
... 

这意味着QTimer创建内部loop()方法永远不会被事件循环执行。

如果我将设计从QWaitCondition更改为信号(这是更好的设计方法),QTimer的工作原理,但我想知道为什么他们不工作时使用QWaitCondition。

回答

3

你的方法完全loop占据线程。 它不会将控制返回到事件循环。 Timer将其事件发送到无法控制的事件循环。
IMO你的wile循环有问题。

解决此问题的一种方法是在循环中添加QApplication.processEvents()(坏方法)。

我想你想别的东西,这里是我的更正:

def loop(self): 
    self.timer = QtCore.QTimer() 
    self.timer.setSingleShot(False) 
    self.timer.timeout.connect(self.do_stuff_timer) 
    self.timer.start(1000) 

def stop(self): 
    self.timer.stop() 

这将调用do_stuff_timer每一秒,直到你将调用停止。

+0

他的QWaitCondition要求如何? – g19fanatic 2013-02-22 16:57:55