【问题标题】:Why can't I initialize a QThread in a member function of class?为什么我不能在类的成员函数中初始化 QThread?
【发布时间】:2014-09-20 15:46:22
【问题描述】:

代码如下:

##########################################################
######## Version 1 (works)
##########################################################
#!/usr/bin/env python3


from ui.qthreadtest import Ui_QthreadTest
from PySide import QtCore, QtGui
import time

class Md(QtGui.QDialog):
    def __init__(self):
        super().__init__()
        self.prcsbtn = QtGui.QPushButton("Process")
        self.prcsedit = QtGui.QLineEdit()
        layout = QtGui.QHBoxLayout()
        layout.addWidget(self.prcsedit)
        layout.addWidget(self.prcsbtn)
        self.setLayout(layout)
        self.prcsbtn.clicked.connect(self.work)

        self.wt = Worker()

    def work(self):
        self.wt.start()
        # the DirectConnection option demands the slot to be triggered immediately
        self.wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection)

    def changeText(self):
        self.prcsedit.setText("Work finished!")

class Worker(QtCore.QThread):
    workFinished = QtCore.Signal()
    def __init__(self):
        super().__init__()

    def run(self):
        time.sleep(2)
        self.workFinished.emit()

import sys
app = QtGui.QApplication(sys.argv)
md = Md()
md.show()
sys.exit(app.exec_())


##########################################################
######## Version 2 (doesn't work)    
##########################################################

#!/usr/bin/env python3


from ui.qthreadtest import Ui_QthreadTest
from PySide import QtCore, QtGui
import time

class Md(QtGui.QDialog):
    def __init__(self):
        super().__init__()
        self.prcsbtn = QtGui.QPushButton("Process")
        self.prcsedit = QtGui.QLineEdit()
        layout = QtGui.QHBoxLayout()
        layout.addWidget(self.prcsedit)
        layout.addWidget(self.prcsbtn)
        self.setLayout(layout)
        self.prcsbtn.clicked.connect(self.work)


    def work(self):
        # the worker thread initialized in a member function won't work.
        wt = Worker()
        wt.start()
        # the DirectConnection option demands the slot to be triggered immediately
        wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection)

    def changeText(self):
        self.prcsedit.setText("Work finished!")

class Worker(QtCore.QThread):
    workFinished = QtCore.Signal()
    def __init__(self):
        super().__init__()

    def run(self):
        time.sleep(2)
        self.workFinished.emit()

import sys
app = QtGui.QApplication(sys.argv)
md = Md()
md.show()
sys.exit(app.exec_())

版本 1 工作正常,版本 2 出现此错误(按下 Process 按钮时会立即崩溃):

QThread: Destroyed while thread is still running

Process finished with exit code 139

【问题讨论】:

  • 错误消息几乎没有让事情变得更明显,特别是因为这两个示例之间唯一真正的区别是一个保持对工作线程的引用,而另一个没有。此外,您应该注意使用direct connection for the signal is not safe

标签: python multithreading qt pyside


【解决方案1】:

发生这种情况是因为与threading.Thread 对象不同,QThread 对象一旦超出范围就会被销毁。在您的示例中,wtwork 结束时超出范围,因此对象被销毁。为避免这种情况,您需要保持对wt 的持久引用。一种方法是使其成为实例变量:

def work(self):
    self.wt = Worker()
    self.wt.start()
    # the DirectConnection option demands the slot to be triggered immediately
    self.wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection)

【讨论】:

    猜你喜欢
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-26
    相关资源
    最近更新 更多