2013-02-22 2 views
2

나는 pyside를 사용하고 있지만 (제 생각에는) 일반적인 Qt 질문입니다.QTimer를 QThread 내부에서 QWaitCondition을 사용하는 방법? (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에서 Signals (더 나은 디자인 imho)로 변경하면 QTimer가 작동하지만 QWaitCondition이 사용될 때 왜 작동하지 않는지 알고 싶습니다.

답변

5

장기 실행 태스크 (일명 연속 루프)에서 이벤트를 계속 처리하려면 QCoreApplication::processEvents()을 호출해야합니다.

이것은 기본적으로 스레드에 대기중인 모든 슬롯을 통과합니다.

신호를 현재 스레드에서 다른 스레드로 내보내려면 신호 (QueuedConnection 신호/슬롯 연결 인 경우)에도이 함수를 호출해야합니다.


는 PySides를 들어, PySide.QtCore.QCoreApplication.processEvents()

3

귀하의 방법 loop 완전히 스레드를 차지 호출해야합니다. 이벤트 루프에 제어를 반환하지 않습니다. Timer는 이벤트를 통제하지 않는 이벤트 루프로 보냅니다.
당신의 위락 루프가 잘못되었습니다.

해결 방법 중 하나는 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

관련 문제