2013-02-22 28 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

相關問題