我有以下pyqtmain.py:
#!/usr/bin/python3 import sys from PyQt4.QtCore import * from PyQt4.QtGui import * from pyqtMeasThread import * class MainWindow(QMainWindow): def __init__(self, parent=None): self.qt_app = QApplication(sys.argv) QMainWindow.__init__(self, parent) buttonWidget = QWidget() rsltLabel = QLabel("Result:") self.rsltFiled = QLineEdit() self.buttonStart = QPushButton("Start") verticalLayout = QVBoxLayout(buttonWidget) verticalLayout.addWidget(rsltLabel) verticalLayout.addWidget(self.rsltFiled) verticalLayout.addWidget(self.buttonStart) butDW = QDockWidget("Control", self) butDW.setWidget(buttonWidget) self.addDockWidget(Qt.LeftDockWidgetArea, butDW) self.mthread = QThread() # New thread to run the Measurement Engine self.worker = MeasurementEngine() # Measurement Engine Object self.worker.moveToThread(self.mthread) self.mthread.finished.connect(self.worker.deleteLater) # Cleanup after thread finished self.worker.measure_msg.connect(self.showRslt) self.buttonStart.clicked.connect(self.worker.run) # Everything configured, start the worker thread. self.mthread.start() def run(self): """ Show the window and start the event loop """ self.show() self.qt_app.exec_() # Start event loop @pyqtSlot(str) def showRslt(self, mystr): self.rsltFiled.setText(mystr) def main(): win = MainWindow() win.run() if __name__ == '__main__': main()
另一个执行实际测量的线程脚本:
from PyQt4.QtCore import * import time class MeasurementEngine(QObject): measure_msg = pyqtSignal(str) def __init__(self): QObject.__init__(self) # Don't forget to call base class constructor @pyqtSlot() def run(self): self.measure_msg.emit('phase1') time.sleep(2) # here I would like to make it as an interrupt self.measure_msg.emit('phase2')
这段代码现在的作用是按下Start按钮后,将执行线程中运行的函数.但是,实际上在功能运行中,测量有两个阶段.现在我用了一段时间.
但我想要实现的是在"阶段1"测量完成之后.将弹出一个消息框,同时线程将被暂停/保持.在用户关闭消息框之前,线程功能将恢复.
使用QWaitCondition
从QtCore
模块.使用互斥锁,将后台线程设置为等待/休眠,直到前台线程将其唤醒.然后它将继续从那里开始工作.
#!/usr/bin/python3 import sys from PyQt4.QtCore import * from PyQt4.QtGui import * from pyqtMeasThread import * class MainWindow(QMainWindow): def __init__(self, parent=None): self.qt_app = QApplication(sys.argv) QMainWindow.__init__(self, parent) buttonWidget = QWidget() rsltLabel = QLabel("Result:") self.rsltFiled = QLineEdit() self.buttonStart = QPushButton("Start") verticalLayout = QVBoxLayout(buttonWidget) verticalLayout.addWidget(rsltLabel) verticalLayout.addWidget(self.rsltFiled) verticalLayout.addWidget(self.buttonStart) butDW = QDockWidget("Control", self) butDW.setWidget(buttonWidget) self.addDockWidget(Qt.LeftDockWidgetArea, butDW) self.mutex = QMutex() self.cond = QWaitCondition() self.mthread = QThread() # New thread to run the Measurement Engine self.worker = MeasurementEngine(self.mutex, self.cond) # Measurement Engine Object self.worker.moveToThread(self.mthread) self.mthread.finished.connect(self.worker.deleteLater) # Cleanup after thread finished self.worker.measure_msg.connect(self.showRslt) self.buttonStart.clicked.connect(self.worker.run) # Everything configured, start the worker thread. self.mthread.start() def run(self): """ Show the window and start the event loop """ self.show() self.qt_app.exec_() # Start event loop # since this is a slot, it will always get run in the event loop in the main thread @pyqtSlot(str) def showRslt(self, mystr): self.rsltFiled.setText(mystr) msgBox = QMessageBox(parent=self) msgBox.setText("Close this dialog to continue to Phase 2.") msgBox.exec_() self.cond.wakeAll() def main(): win = MainWindow() win.run() if __name__ == '__main__': main()
和:
from PyQt4.QtCore import * import time class MeasurementEngine(QObject): measure_msg = pyqtSignal(str) def __init__(self, mutex, cond): QObject.__init__(self) # Don't forget to call base class constructor self.mtx = mutex self.cond = cond @pyqtSlot() def run(self): # NOTE: do work for phase 1 here self.measure_msg.emit('phase1') self.mtx.lock() try: self.cond.wait(self.mtx) # NOTE: do work for phase 2 here self.measure_msg.emit('phase2') finally: self.mtx.unlock()
尽管如此,你的时间有点偏差.您甚至可以在显示窗口之前创建应用程序并启动线程.因此,在主窗口弹出之前将弹出消息框.要获得正确的事件序列,您应该在已经使主窗口可见之后将线程作为run
MainWindow方法的一部分启动.如果您希望等待条件与消息设置分开,您可能需要一个单独的信号和插槽来处理它.