Qthread

时间:2018-09-05 05:57:28

标签: python pyqt pyqt5 qthread

我想访问QThread类中的父类窗口小部件

此行给出了挂起的GUI“ Example()。setWindowTitle(” Window“)”

我该怎么做?

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.myclass2 = myclass2()
        self.myclass2.start()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('web.png'))
        self.show()


class myclass2(QThread):
    def __init__(self, parent=None):
        super(myclass2, self).__init__(parent)

    def run(self):
        while True:
            time.sleep(.1)
            print(" in thread \n")
            Example().setWindowTitle("Window")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

您必须了解以下表达式:

Example().setWindowTitle("Window")

它等效于:

obj = Example()
obj.setWindowTitle("Window")

也就是说,您正在创建ex = Example()以外的另一个Example对象,并且该对象正在创建另一个myclass2对象,而另一个myclass2对象正在创建另一个Example,以及一个无穷大显然正在创建循环。


将来可能导致您遇到问题的另一件事是为不同的事物建立相同的名称,尽管在这种情况下这不是问题,但是在将来的情况下可能会给您带来麻烦,我引用的代码是:

self.myclass2 = myclass2()

例如,建议类应以大写字母开头。


另一个仅在Qt中有效的错误是,无法在除主线程之外的其他线程中创建或操纵GUI。因此,您不能直接在另一个线程中更改标题,但是有2种方法:

1。 QMetaObject::invokeMethod(...)

但是为此,我们必须通过属性传递GUI:

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.myclass2 = MyClass()
        self.myclass2.gui = self
        self.myclass2.start()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('web.png'))
        self.show()


class MyClass(QThread):
    def run(self):
        while True:
            time.sleep(.1)
            print(" in thread \n")
            QMetaObject.invokeMethod(self.gui, "setWindowTitle", Qt.QueuedConnection, Q_ARG(str, "Window"))

2。信号和插槽

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.myclass2 = MyClass()
        self.myclass2.titleChanged.connect(self.setWindowTitle)
        self.myclass2.start()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('web.png'))
        self.show()


class MyClass(QThread):
    titleChanged = pyqtSignal(str)

    def run(self):
        while True:
            time.sleep(.1)
            print(" in thread \n")
            self.titleChanged.emit("Window")

加号:

您不应直接从线程修改GUI,而应通过信号发送数据:

import sys

from PyQt5 import QtCore, QtGui, QtWidgets

class Example(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        lay = QtWidgets.QVBoxLayout(self)
        le = QtWidgets.QLineEdit()
        lay.addWidget(le)
        self.myclass2 = MyClass()
        self.myclass2.titleChanged.connect(self.setWindowTitle)
        self.myclass2.infoChanged.connect(le.setText) # <-- connect signal
        self.myclass2.start()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QtGui.QIcon('web.png'))
        self.show()


class MyClass(QtCore.QThread):
    titleChanged = QtCore.pyqtSignal(str)
    infoChanged = QtCore.pyqtSignal(str) # <-- create signal

    def run(self):
        counter = 0
        while True:
            QtCore.QThread.msleep(100)
            print(" in thread \n")
            self.titleChanged.emit("Window")
            self.infoChanged.emit("{}".format(counter)) # <-- emit signal
            counter += 1


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())