我正在使用 pyside 但(我认为)是一个通用的 Qt 问题。
我知道 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
...
这意味着在 loop() 方法中创建的 QTimer 永远不会被事件循环执行。
如果我将设计从 QWaitCondition 更改为 Signals(这是更好的设计恕我直言),QTimer 可以工作,但我想知道为什么在使用 QWaitCondition 时它们不工作。