Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从要插入到QTreeWidget的QThread生成的QWidget的正确父级_Python_Multithreading_Pyqt_Widget - Fatal编程技术网

Python 从要插入到QTreeWidget的QThread生成的QWidget的正确父级

Python 从要插入到QTreeWidget的QThread生成的QWidget的正确父级,python,multithreading,pyqt,widget,Python,Multithreading,Pyqt,Widget,我有一个QTreeWidget,它需要填充大量信息。为了能够按照我真正想要的方式来设计和设置它,我决定创建一个QWidget,它的样式和穿着都非常漂亮。然后,我将使用通用的TreeWidgetItems填充TreeWidget,然后使用setItemWidget将定制的QWidget粘贴到树中。当在主PyQt线程内调用QWidget时,这是可行的,但是由于有大量的信息,我想在线程中创建和填充QWidget,然后在填充完之后将它们发送到主线程中。然而,当我这样做时,QWidget似乎没有正确设置它

我有一个QTreeWidget,它需要填充大量信息。为了能够按照我真正想要的方式来设计和设置它,我决定创建一个QWidget,它的样式和穿着都非常漂亮。然后,我将使用通用的TreeWidgetItems填充TreeWidget,然后使用setItemWidget将定制的QWidget粘贴到树中。当在主PyQt线程内调用QWidget时,这是可行的,但是由于有大量的信息,我想在线程中创建和填充QWidget,然后在填充完之后将它们发送到主线程中。然而,当我这样做时,QWidget似乎没有正确设置它们的父窗口,因为它们都在自己的小窗口中打开。以下是重新创建此问题的一些示例代码:

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class ItemWidget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        btn = QPushButton(self)

class populateWidgets(QThread):
    def __init__(self):
        QThread.__init__(self)

    def run(self):
        widget = ItemWidget()
        for x in range(5):
            self.emit(SIGNAL("widget"), widget)

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.tree = QTreeWidget(self)
        self.tree.setColumnCount(2)
        self.setCentralWidget(self.tree)

        self.pop = populateWidgets()
        self.connect(self.pop, SIGNAL("widget"), self.addItems)
        self.pop.start()

        itemWidget = QTreeWidgetItem()
        itemWidget.setText(0, "This Works")
        self.tree.addTopLevelItem(itemWidget)
        self.tree.setItemWidget(itemWidget, 1, ItemWidget(self))        

    def addItems(self, widget):
        itemWidget = QTreeWidgetItem()
        itemWidget.setText(0, "These Do Not")
        self.tree.addTopLevelItem(itemWidget)
        self.tree.setItemWidget(itemWidget, 1, widget)

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    ui = MyMainWindow()
    ui.show()
    sys.exit(app.exec_())

正如您所看到的,在MyMainWindow中执行该操作是可以的,但是一旦它在线程中得到处理并返回,就会出现一些问题。这可能吗?如果是这样,我如何在QTreeWidgetItem中正确设置ItemWidget类的父级?提前感谢。

AFAICT Qt不支持在QApplication对象实例化的线程(即通常是main()线程)之外的线程中创建QWidget。以下是一些关于该主题的帖子,以及Qt开发人员的回复:


(如果可能的话,方法是从主线程中调用QWidget上的moveToThread(),将它们移动到主线程——但显然,这种技术无法可靠地工作,因为QtCore有一个检查,检查试图这样做的人,它会向标准输出一条警告,告诉他们不要这样做)AFAICT Qt不支持在QApplication对象实例化的线程(即通常是main()线程)之外的线程中创建QWidgets。以下是一些关于该主题的帖子,以及Qt开发人员的回复:


(如果可能的话,方法是从主线程中调用QWidget上的moveToThread(),将它们移动到主线程——但显然,这种技术无法可靠地工作,因为QtCore有一个检查,检查试图这样做的人,它会向标准输出一条警告,告诉他们不要这样做)

将小部件添加到主线程中的树中,然后将每个小部件传递到线程以确保安全,这样安全吗?我想的唯一的另一种方式是查询线程中的字典中的所有信息,然后发出这些信息并使用它来填充小部件数据。我认为从不同的线程中更新GUI是不安全的。。。因此,您的代码可以在QWidget子类中设置Qt不知道的数据,但是从线程到Qt自己的GUI/widget代码的任何调用都可能会让您感到悲伤。我喜欢您的第二个想法,即在另一个线程中准备数据,然后将数据发送回主线程以将数据移动到GUI中;那应该更有效。是的,我同意。谢谢你,杰里米!将小部件添加到主线程中的树中,然后将每个小部件传递到线程以确保安全,这样安全吗?我想的唯一的另一种方式是查询线程中的字典中的所有信息,然后发出这些信息并使用它来填充小部件数据。我认为从不同的线程中更新GUI是不安全的。。。因此,您的代码可以在QWidget子类中设置Qt不知道的数据,但是从线程到Qt自己的GUI/widget代码的任何调用都可能会让您感到悲伤。我喜欢您的第二个想法,即在另一个线程中准备数据,然后将数据发送回主线程以将数据移动到GUI中;那应该更有效。是的,我同意。谢谢你,杰里米!