我目前正在尝试构建一个PyQt5应用程序,它应该包含主GUI,并且在后台应该有一个不同的线程,应该在无限循环中测量某些东西。我想使用QAction或Checkbox启动和停止此线程。
所以说当我按下复选框并且状态为true时,应该启动线程,如果我再次点击它,它应该被停止。
现在实现这个的最佳方法是什么?
目前我正在使用像这样的工作线程:
class Worker(QtCore.QObject):
def __init__(self):
super(Worker, self).__init__()
self._isRunning = True
def task(self):
if not self._isRunning:
self._isRunning = True
while self._isRunning:
time.sleep(0.5)
... measure ...
def stop(self):
self._isRunning = False
并在主线程中使其运行:
self.thread = QtCore.QThread()
self.thread.start()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.btn_start.clicked.connect(self.worker.task)
self.btn_stopped.clicked.connect(lambda: self.worker.stop())
到目前为止这是有效的。但我并不确信这是最好的方法,如果我能按照描述的方式使用复选框做同样的事情,我也会更喜欢它。
答案 0 :(得分:1)
目前,您发布的代码不是多线程的。这是因为worker.task()
是由主线程中的代码启动的,因此它也将在主线程中运行。您需要使用工作线程的started
信号来启动任务,并在工作人员上使用自定义信号来退出线程。
下面的演示脚本应解决这些问题:
import sys, time
from PyQt5 import QtCore, QtWidgets
class Worker(QtCore.QObject):
finished = QtCore.pyqtSignal()
messageSent = QtCore.pyqtSignal(str)
def __init__(self):
super(Worker, self).__init__()
self._isRunning = False
def task(self):
print('WKR thread:', QtCore.QThread.currentThread())
self._isRunning = True
count = 0
while self._isRunning:
time.sleep(0.5)
count += 1
self.messageSent.emit('count: %s' % count)
self.finished.emit()
def stop(self):
self._isRunning = False
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QtWidgets.QCheckBox('Test', self)
self.button.toggled.connect(self.handleButton)
self.label = QtWidgets.QLabel(self)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.button)
self.thread = QtCore.QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.task)
self.worker.finished.connect(self.thread.quit)
self.worker.messageSent.connect(self.label.setText)
def handleButton(self, checked=False):
print('GUI thread:', QtCore.QThread.currentThread())
if checked:
self.label.clear()
self.thread.start()
else:
self.worker.stop()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(800, 150, 200, 50)
window.show()
sys.exit(app.exec_())