Qthread中的Python访问父类的小部件

时间:2023-03-11
本文介绍了Qthread中的Python访问父类的小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

I want to access the parent class widgets in the QThread class

这一行给出了挂起 GUI "Example().setWindowTitle("Window")"

This line gives hangs 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 
")
            Example().setWindowTitle("Window")

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

推荐答案

你必须明白下面的表达:

You must understand the following expression:

Example().setWindowTitle("Window")

相当于:

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

也就是说,您正在创建除 ex = Example() 之外的另一个 Example 对象,并且该对象正在创建另一个 myclass2 对象,以及另一个 myclass2 对象正在创建另一个示例,并且显然正在创建一个无限循环.

That is, you are creating another Example object other than ex = Example(), and that object is creating another myclass2 object, and that other myclass2 object is creating another Example, and an infinite loop is clearly being created.

将来可能给您带来问题的另一件事是为不同的事物建立相同的名称,虽然在这种情况下这不是问题但在将来的情况下可能会给您带来问题,我参考的代码是:

Another thing that in the future could cause you problems is to establish the same name for different things, although in this case it is not a problem but in future occasions it could bring you problems, the code to which I refer is:

self.myclass2 = myclass2()

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

For example, it is recommended that classes should start with capital letters.

另一个仅在 Qt 中有效的错误是不能在主线程以外的线程中创建或操作 GUI.所以你不能直接在另一个线程中更改标题,但有两种方法:

Another error that is valid only in Qt is that the GUI can not be created or manipulated in a thread other than the main thread. So you can not change the title directly in the other thread but there are 2 methods:

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

But for this we must pass the GUI through a property:

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 
")
            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 
")
            self.titleChanged.emit("Window")

加:

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

You should not modify the GUI from the thread directly but send the data through a signal:

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 
")
            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_())

这篇关于Qthread中的Python访问父类的小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:QMouseEvent' 对象没有属性 'pos' 下一篇:在QMainWindow中放置一个小部件,如何定位而不是setCentralWidget

相关文章