How to use QTimer inside QThread which uses QWaitCondition? (pyside)
我正在使用pyside,但是(我认为)是一个通用的Qt问题。
我知道QThread实现会调用._exec()方法,因此我们应该在启动的QThread上有一个事件循环。 这样,我们可以在该线程上使用QTimer(我已经做到了,它可以完美地工作)。 我的问题是,当还使用QWaitCondition时,我希望有一个带有无限循环的"消费者"线程,等待(从生产者处)在QWaitCondition上进行通知。 我的问题是,使用这种设计,我无法在使用者线程内使用QTimer。
这是我要解释的场景的摘要:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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_()) |
单击按钮后,我们将获得如下输出:
1 2 3 4 5 | 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时它们不起作用。
若要仍在长时间运行的任务(也称为连续循环)中处理事件,则需要调用
这实际上将穿过线程的所有排队的插槽。
对于信号(如果它们是QueuedConnection信号/插槽连接),也必须调用此函数才能使其从当前线程进入另一个线程。
对于PySides,您需要调用
您的方法
它不会将控制权返回给事件循环。 计时器将其事件发送到无法获得控制的事件循环。
IMO您的恶意循环有问题。
解决此问题的一种方法是在循环中添加
我认为您还想要其他东西,这是我的更正:
1 2 3 4 5 6 7 8 | 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() |
这将每秒调用一次