PyQt QThread:如何 运行 同一线程中工作对象上的函数?
PyQt QThread: How to run a function on a worker object in the same thread?
我只是不知道如何正确使用 QThreads。我有一个工作对象,这里有一个有两个组合框的图形用户界面:当用户在 comboWorkspace 上选择一个项目时,将加载 comboModel 上的项目。发生的事情是,每当我从 comboWorkspace 中选择时,它都会再次 运行 来自 worker 的 get_workspaces 函数。这可能是因为我一遍又一遍地调用 QThread 的 "start" 函数。如果这里有很多问题,我很抱歉。如果有人能给 ma 一个关于如何正确处理这个问题的想法。非常感谢!
*setupUi 函数的完整代码在这里:pastebin。com/Y7dGbRLu
from PyQt5 import QtCore, QtGui, QtWidgets
import os
import time
from functools import partial
import copy
class anaplanWorker(QtCore.QObject):
signal_workspacenames = QtCore.pyqtSignal(str)
signal_modelnames = QtCore.pyqtSignal(str)
finish_progressbar = QtCore.pyqtSignal()
start_progressbar = QtCore.pyqtSignal()
finish_workspace_thread = QtCore.pyqtSignal()
finish_model_thread = QtCore.pyqtSignal()
count_run = 0
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
def get_workspaces(self):
ws_names = ['Name One', 'Name Two', 'Name Three']
self.start_progressbar.emit()
for ws_name in ws_names:
self.signal_workspacenames.emit(ws_name)
self.finish_workspace_thread.emit()
def get_models(self,workspaceindex):
self.start_progressbar.emit()
models = ['Model One', 'Model Two', 'Model Three']
for model_name in models:
self.signal_modelnames.emit(model_name)
self.finish_model_thread.emit()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
"""ui setup for combo combo boxes: comboWorkspace and comboModel"""
def progress_start(self):
print("start")
def progress_finish(self):
print("finish")
#workspace functions
def add_workspace(self, workspace_name):
self.comboWorkspace.addItem(workspace_name)
def start_workspace(self):
self.comboWorkspace.clear()
self.workspace_thread = self.anaplan_thread
self.anaplan_worker.moveToThread(self.workspace_thread)
self.workspace_thread.started.connect(self.anaplan_worker.get_workspaces)
self.workspace_thread.start()
#model functions
def add_model(self, model_name):
self.comboModel.addItem(model_name)
def start_model(self):
#clear combomodel
self.comboModel.clear()
workspaceIndex = self.comboWorkspace.currentIndex()
self.model_thread = self.anaplan_thread
self.anaplan_worker.moveToThread(self.model_thread)
self.model_thread.started.connect(partial(self.anaplan_worker.get_models, workspaceIndex))
self.model_thread.start()
#quit threads
def quit_model_thread(self):
self.model_thread.quit()
print("quit model thread")
def quit_workspace_thread(self):
self.workspace_thread.quit()
print("quit workspace thread")
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Tool"))
self.labelWorkspace.setText(_translate("MainWindow", "Workspace"))
self.labelModel.setText(_translate("MainWindow", "Model"))
self.anaplan_worker = anaplanWorker()
self.anaplan_thread = QtCore.QThread()
self.anaplan_worker.signal_workspacenames.connect(self.add_workspace)
self.anaplan_worker.signal_modelnames.connect(self.add_model)
self.anaplan_worker.finish_workspace_thread.connect(self.quit_workspace_thread)
self.anaplan_worker.finish_model_thread.connect(self.quit_model_thread)
self.comboWorkspace.activated[str].connect(self.start_model)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
ui.start_workspace()
sys.exit(app.exec_())
你应该更多地拆分你的代码。它会解决你的很多问题。
您有两个主要问题:每次更改索引时都需要重新设置 signals/slots 连接(一个连接意味着一个调用)。您正在为两个不同的任务使用同一个线程。
您应该创建一个新的 class MainWindow
并在其中移动您的业务逻辑。您的 Ui_MainWindow
class 应该只处理 UI 部分(小部件、布局等)。
你的 anaplanWorker
有一堆问题:它从 QObject
继承但调用 QThread.__init__
并且你用它来创建一个线程和一个对象 worker。直接用QThread
.
会更清楚
class 应该分成两个不同的部分,另外:一个用于工作区,一个用于模型:
class ModelWorker(QtCore.QObject):
signal_modelnames = QtCore.pyqtSignal(str)
finish_progressbar = QtCore.pyqtSignal()
start_progressbar = QtCore.pyqtSignal()
finish_model_thread = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
def get_models(self,workspaceindex):
print("Get models with", workspaceindex)
self.start_progressbar.emit()
models = ['Model One', 'Model Two', 'Model Three']
for model_name in models:
self.signal_modelnames.emit(model_name)
self.finish_model_thread.emit()
class WorkspaceWorker(QtCore.QObject):
signal_workspacenames = QtCore.pyqtSignal(str)
finish_progressbar = QtCore.pyqtSignal()
start_progressbar = QtCore.pyqtSignal()
finish_workspace_thread = QtCore.pyqtSignal()
finish_model_thread = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
def get_workspaces(self):
ws_names = ['Name One', 'Name Two', 'Name Three']
self.start_progressbar.emit()
for ws_name in ws_names:
self.signal_workspacenames.emit(ws_name)
self.finish_workspace_thread.emit()
然后,在您的 MainWindow class 中,创建并设置线程和连接。您只需要在需要时启动线程即可。
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.workspaceWorker = WorkspaceWorker()
self.modelWorker = ModelWorker()
self.workspaceWorker_thread = QThread(self)
self.modelWorker_thread = QThread(self)
self.workspaceWorker.moveToThread(self.workspaceWorker_thread)
self.modelWorker.moveToThread(self.modelWorker_thread)
self.workspaceWorker.signal_workspacenames.connect(self.add_workspace)
self.workspaceWorker.finish_workspace_thread.connect(self.quit_workspace_thread)
self.modelWorker.signal_modelnames.connect(self.add_model)
self.modelWorker.finish_model_thread.connect(self.quit_model_thread)
self.comboWorkspace.activated[str].connect(self.start_model)
self.modelWorker_thread.started.connect(lambda: self.modelWorker.get_models(self.comboWorkspace.currentIndex()))
self.workspaceWorker_thread.started.connect(self.workspaceWorker.get_workspaces)
self.start_workspace()
def add_workspace(self, workspace_name):
self.comboWorkspace.addItem(workspace_name)
def start_workspace(self):
self.comboWorkspace.clear()
self.workspaceWorker_thread.start()
#model functions
def add_model(self, model_name):
self.comboModel.addItem(model_name)
def start_model(self):
#clear combomodel
self.comboModel.clear()
self.modelWorker_thread.start()
#quit threads
def quit_model_thread(self):
self.modelWorker_thread.quit()
print("quit model thread")
def quit_workspace_thread(self):
self.workspaceWorker_thread.quit()
print("quit workspace thread")
我只是不知道如何正确使用 QThreads。我有一个工作对象,这里有一个有两个组合框的图形用户界面:当用户在 comboWorkspace 上选择一个项目时,将加载 comboModel 上的项目。发生的事情是,每当我从 comboWorkspace 中选择时,它都会再次 运行 来自 worker 的 get_workspaces 函数。这可能是因为我一遍又一遍地调用 QThread 的 "start" 函数。如果这里有很多问题,我很抱歉。如果有人能给 ma 一个关于如何正确处理这个问题的想法。非常感谢!
*setupUi 函数的完整代码在这里:pastebin。com/Y7dGbRLu
from PyQt5 import QtCore, QtGui, QtWidgets
import os
import time
from functools import partial
import copy
class anaplanWorker(QtCore.QObject):
signal_workspacenames = QtCore.pyqtSignal(str)
signal_modelnames = QtCore.pyqtSignal(str)
finish_progressbar = QtCore.pyqtSignal()
start_progressbar = QtCore.pyqtSignal()
finish_workspace_thread = QtCore.pyqtSignal()
finish_model_thread = QtCore.pyqtSignal()
count_run = 0
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
def get_workspaces(self):
ws_names = ['Name One', 'Name Two', 'Name Three']
self.start_progressbar.emit()
for ws_name in ws_names:
self.signal_workspacenames.emit(ws_name)
self.finish_workspace_thread.emit()
def get_models(self,workspaceindex):
self.start_progressbar.emit()
models = ['Model One', 'Model Two', 'Model Three']
for model_name in models:
self.signal_modelnames.emit(model_name)
self.finish_model_thread.emit()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
"""ui setup for combo combo boxes: comboWorkspace and comboModel"""
def progress_start(self):
print("start")
def progress_finish(self):
print("finish")
#workspace functions
def add_workspace(self, workspace_name):
self.comboWorkspace.addItem(workspace_name)
def start_workspace(self):
self.comboWorkspace.clear()
self.workspace_thread = self.anaplan_thread
self.anaplan_worker.moveToThread(self.workspace_thread)
self.workspace_thread.started.connect(self.anaplan_worker.get_workspaces)
self.workspace_thread.start()
#model functions
def add_model(self, model_name):
self.comboModel.addItem(model_name)
def start_model(self):
#clear combomodel
self.comboModel.clear()
workspaceIndex = self.comboWorkspace.currentIndex()
self.model_thread = self.anaplan_thread
self.anaplan_worker.moveToThread(self.model_thread)
self.model_thread.started.connect(partial(self.anaplan_worker.get_models, workspaceIndex))
self.model_thread.start()
#quit threads
def quit_model_thread(self):
self.model_thread.quit()
print("quit model thread")
def quit_workspace_thread(self):
self.workspace_thread.quit()
print("quit workspace thread")
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Tool"))
self.labelWorkspace.setText(_translate("MainWindow", "Workspace"))
self.labelModel.setText(_translate("MainWindow", "Model"))
self.anaplan_worker = anaplanWorker()
self.anaplan_thread = QtCore.QThread()
self.anaplan_worker.signal_workspacenames.connect(self.add_workspace)
self.anaplan_worker.signal_modelnames.connect(self.add_model)
self.anaplan_worker.finish_workspace_thread.connect(self.quit_workspace_thread)
self.anaplan_worker.finish_model_thread.connect(self.quit_model_thread)
self.comboWorkspace.activated[str].connect(self.start_model)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
ui.start_workspace()
sys.exit(app.exec_())
你应该更多地拆分你的代码。它会解决你的很多问题。
您有两个主要问题:每次更改索引时都需要重新设置 signals/slots 连接(一个连接意味着一个调用)。您正在为两个不同的任务使用同一个线程。
您应该创建一个新的 class MainWindow
并在其中移动您的业务逻辑。您的 Ui_MainWindow
class 应该只处理 UI 部分(小部件、布局等)。
你的 anaplanWorker
有一堆问题:它从 QObject
继承但调用 QThread.__init__
并且你用它来创建一个线程和一个对象 worker。直接用QThread
.
class 应该分成两个不同的部分,另外:一个用于工作区,一个用于模型:
class ModelWorker(QtCore.QObject):
signal_modelnames = QtCore.pyqtSignal(str)
finish_progressbar = QtCore.pyqtSignal()
start_progressbar = QtCore.pyqtSignal()
finish_model_thread = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
def get_models(self,workspaceindex):
print("Get models with", workspaceindex)
self.start_progressbar.emit()
models = ['Model One', 'Model Two', 'Model Three']
for model_name in models:
self.signal_modelnames.emit(model_name)
self.finish_model_thread.emit()
class WorkspaceWorker(QtCore.QObject):
signal_workspacenames = QtCore.pyqtSignal(str)
finish_progressbar = QtCore.pyqtSignal()
start_progressbar = QtCore.pyqtSignal()
finish_workspace_thread = QtCore.pyqtSignal()
finish_model_thread = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
def get_workspaces(self):
ws_names = ['Name One', 'Name Two', 'Name Three']
self.start_progressbar.emit()
for ws_name in ws_names:
self.signal_workspacenames.emit(ws_name)
self.finish_workspace_thread.emit()
然后,在您的 MainWindow class 中,创建并设置线程和连接。您只需要在需要时启动线程即可。
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.workspaceWorker = WorkspaceWorker()
self.modelWorker = ModelWorker()
self.workspaceWorker_thread = QThread(self)
self.modelWorker_thread = QThread(self)
self.workspaceWorker.moveToThread(self.workspaceWorker_thread)
self.modelWorker.moveToThread(self.modelWorker_thread)
self.workspaceWorker.signal_workspacenames.connect(self.add_workspace)
self.workspaceWorker.finish_workspace_thread.connect(self.quit_workspace_thread)
self.modelWorker.signal_modelnames.connect(self.add_model)
self.modelWorker.finish_model_thread.connect(self.quit_model_thread)
self.comboWorkspace.activated[str].connect(self.start_model)
self.modelWorker_thread.started.connect(lambda: self.modelWorker.get_models(self.comboWorkspace.currentIndex()))
self.workspaceWorker_thread.started.connect(self.workspaceWorker.get_workspaces)
self.start_workspace()
def add_workspace(self, workspace_name):
self.comboWorkspace.addItem(workspace_name)
def start_workspace(self):
self.comboWorkspace.clear()
self.workspaceWorker_thread.start()
#model functions
def add_model(self, model_name):
self.comboModel.addItem(model_name)
def start_model(self):
#clear combomodel
self.comboModel.clear()
self.modelWorker_thread.start()
#quit threads
def quit_model_thread(self):
self.modelWorker_thread.quit()
print("quit model thread")
def quit_workspace_thread(self):
self.workspaceWorker_thread.quit()
print("quit workspace thread")