所以,我是一个新手,他正在尝试重新发明轮子,并在PySide2中以正确的方式进行线程处理。 我的问题是,我的线程似乎启动得很好,但它应该执行的函数没有输出,我不明白为什么
下面是我如何设置的一个简短解释,以及一个最小的可复制示例。 我有一个文件,比如说它叫做“sou helpers”,用于演示。内部有两个类,一个是名为“External”的QThread,我试图以智能方式构造和运行它(显然不是,因为它不工作),另一个是Updater,我试图将其方法传递给外部执行。以下是我的“so_助手”的代码:
from PySide2.QtCore import QThread, Signal
class Updater:
def __init__(self):
print("connection to db established")
def process(self):
print("started")
print("doing the update")
print("finished")
class External(QThread):
finished = Signal()
def __init__(self, func):
super().__init__()
self.func = func
def run(self):
self.func()
self.finished.emit()
这是我的ui,在本例中,我们称之为“for_SO_ui”。它由pyuic5从.ui文件自动生成:
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(644, 187)
MainWindow.setMinimumSize(QtCore.QSize(644, 187))
MainWindow.setMaximumSize(QtCore.QSize(644, 187))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(80, 30, 491, 111))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "THREADING IS AWESOME!"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
这里是main.py,所有这些都应该放在一起(但事实并非如此,这让我很难过):
from so_helpers import *
from for_SO_ui import *
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import QThread, Signal
import sys
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
startThread = Signal()
threadDone = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.connectSignals()
def connectSignals(self):
self.pushButton.clicked.connect(self.onButtonClick)
self.startThread.connect(self.onThreadStart)
self.threadDone.connect(self.onThreadDone)
def onButtonClick(self):
self.startThread.emit()
def onThreadStart(self):
self.thread_object = External(self.threadFunction)
self.thread = QThread()
self.thread_object.moveToThread(self.thread)
self.thread_object.finished.connect(self.onThreadDone)
self.thread.start()
def onThreadDone(self):
self.thread.start()
def threadFunction(self):
func = Updater.process
return func
def closeEvent(self, event):
self.thread.quit()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
非常感谢您的任何帮助、解释和建议
您的代码存在多个问题
首先,
External
已经是一个QThread子类,不需要创建一个新线程将其放入。即使在这种情况下,无论何时将QObject移动到另一个线程,都应该将该线程的started
信号连接到应该执行的实际函数(在您的情况下,run
)调用
self.func()
将不运行process
函数,而是运行threadFunction
,它只返回Updater.process
然后,您希望访问函数,但返回的是未绑定的类方法(
Updater.process
),而不是实例方法,因此调用它会导致异常,因为process
至少需要一个参数(self
)。您可以使用
@staticmethod
(并删除self
),或者创建类的实例最后,QThread已经有一个} 的文档中所述:
finished()
信号,您不应该覆盖它,也不应该使用您自己的信号来重新启动线程:当您发出自己的信号时,线程仍在运行,结果可能是它不会再次启动,如有关^{因此,您可以使用原始的QThread} 等待完成,然后再次启动它
finished
信号,或者使用^{这是对代码的可能更正:
PS:供将来参考:如果为了更好地理解代码而不需要文档字符串/注释,请删除它们。
相关问题 更多 >
编程相关推荐