调用一个类在一个窗口中构建一个QTreeWidget:参数1有一个意想不到的类型“Ui_MainWindow”

时间:2021-05-22 23:05:55

I'm using code that I got from ekhumoro to dynamically create a tree from an xml file for a GUI that I've created, however when attempting to call the class inside the _ui.py file generated from pyuic4 I'm getting the Ui_MainWindow class returned instead of the expected argument.

我使用的代码是我从eko得到的,从一个xml文件中动态地创建一个树,这是我创建的一个GUI,但是在尝试调用_ui中的类时。由pyuic4生成的py文件将返回Ui_MainWindow类,而不是预期的参数。

XmlHandler, which creates the tree items (from my understanding):

创建树项的XmlHandler(根据我的理解):

from PyQt4 import QtCore, QtGui, QtXml
from PyQt4.QtXml import *


class XmlHandler(QXmlDefaultHandler):
    def __init__(self, root):
        QtXml.QXmlDefaultHandler.__init__(self)
        self._root = root
        self._item = None
        self._text = ''
        self._error = ''

    def startElement(self, namespace, name, qname, attributes):
        if qname == 'Machine' or qname == 'Feature':
            if self._item is not None:
                self._item = QtGui.QTreeWidgetItem(self._item)
            else:
                self._item = QtGui.QTreeWidgetItem(self._root)
            self._item.setData(0, QtCore.Qt.UserRole, qname)
            self._item.setText(0, 'Unknown Machine')
            if qname == 'Machine':
                self._item.setExpanded(False)
                self._item.setCheckState(0, QtCore.Qt.Unchecked)
                self._item.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsDragEnabled|QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled|QtCore.Qt.ItemIsTristate)
            elif qname == 'FeatureName':
                self._item.setText(1, self._text)
        self._text = ''
        return True

    def endElement(self, namespace, name, qname):
        if qname == 'FeatureName' or qname == 'MachineName':
            if self._item is not None:
                self._item.setText(0, self._text)
                self._item.setCheckState(0, QtCore.Qt.Unchecked)
        elif qname == 'Feature' or qname == 'Machine':
            self._item = self._item.parent()
        return True

    def characters(self, text):
        self._text += text
        return True

    def fatalError(self, exception):
        print('Parse Error: line %d, column %d:\n  %s' % (
              exception.lineNumber(),
              exception.columnNumber(),
              exception.message(),
              ))
        return False

The Class that uses XmlHandler to make the widget:

使用XmlHandler来制作小部件的类:

class MakeWidget(QtGui.QTreeWidget):
    def __init__(self):
        QtGui.QTreeWidget.__init__(self)
        self.header().setResizeMode(QtGui.QHeaderView.Stretch)
        self.setHeaderLabels(['Servers and Services'])
        source = QtXml.QXmlInputSource()
        source.setData(xml)
        handler = XmlHandler(self)
        reader = QtXml.QXmlSimpleReader()
        reader.setContentHandler(handler)
        reader.setErrorHandler(handler)
        reader.parse(source)

Me fumbling around and attempting to use it in my GUI:

我摸索着,试图在我的GUI中使用它:

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(950, 500)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMaximumSize(QtCore.QSize(950, 500))
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.tabWidget = QtGui.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 960, 421))
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth())
        self.tabWidget.setSizePolicy(sizePolicy)
        self.tabWidget.setMaximumSize(QtCore.QSize(960, 430))
        self.tabWidget.setAutoFillBackground(True)
        self.tabWidget.setStyleSheet(_fromUtf8(""))
        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
        self.tabLogPuller = QtGui.QWidget()
        self.tabLogPuller.setObjectName(_fromUtf8("tabLogPuller"))
        self.groupBoxServiceSelection = QtGui.QGroupBox(self.tabLogPuller)
        self.groupBoxServiceSelection.setGeometry(QtCore.QRect(0, 0, 381, 351))
        font = QtGui.QFont()
        font.setBold(False)
        font.setWeight(50)
        self.groupBoxServiceSelection.setFont(font)
        self.groupBoxServiceSelection.setAutoFillBackground(True)
        self.groupBoxServiceSelection.setObjectName(_fromUtf8("groupBoxServiceSelection"))
        self.treeServiceSelection = MakeWidget()
        self.treeServiceSelection.setHeaderLabels(['Servers and Services'])
        self.treeServiceSelection.source = QtXml.QXmlInputSource()
        self.treeServiceSelection.source.setData(xml)
        self.treeServiceSelection.handler = XmlHandler(self)
        self.treeServiceSelection.reader = QtXml.QXmlSimpleReader()
        self.treeServiceSelection.reader.setContentHandler(self.treeServiceSelection.handler)
        self.treeServiceSelection.reader.setErrorHandler(self.treeServiceSelection.handler)
        self.treeServiceSelection.reader.parse(self.treeServiceSelection.source)
        self.treeServiceSelection.setGeometry(QtCore.QRect(10, 80, 161, 261))
        self.treeServiceSelection.setObjectName(_fromUtf8("treeServiceSelection"))

And the errors that I get when attempting to run the file:

当我试图运行文件时所犯的错误:

error triggered by consumer
    self._item = QtGui.QTreeWidgetItem(self._root)
TypeError: arguments did not match any overloaded call:
  QTreeWidgetItem(int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(list-of-str, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidget, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidget, list-of-str, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidget, QTreeWidgetItem, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidgetItem, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidgetItem, list-of-str, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidgetItem, QTreeWidgetItem, int type=QTreeWidgetItem.Type): argument 1 has unexpected type 'Ui_MainWindow'
  QTreeWidgetItem(QTreeWidgetItem): argument 1 has unexpected type 'Ui_MainWindow'

So I guess that my question is: How do I call this class and pass the correct arguments inside the UI_MainWindow class instead of calling what I'm assuming is the parent?

所以我想我的问题是:我如何调用这个类并在UI_MainWindow类中传递正确的参数而不是调用我假设的父类?

1 个解决方案

#1


1  

You create an instance of MakeWidget here:

在这里创建MakeWidget的实例:

    self.treeServiceSelection = MakeWidget()

which then sets up the XmlReader and so forth in its __init__. But, mysteriously, you then attempt to repeat it all in the following lines:

然后在其__init__中设置XmlReader等。但是,神秘地,你试图重复这一切在以下几行:

    self.treeServiceSelection.setHeaderLabels(['Servers and Services'])
    self.treeServiceSelection.source = QtXml.QXmlInputSource()
    self.treeServiceSelection.source.setData(xml)
    ...

What are you trying do here? If you need to adjust the initialization of the MakeWidget class, modify the code in its __init__.

你在这里做什么?如果需要调整MakeWidget类的初始化,请修改其__init__中的代码。

The actual error is caused by this line:

实际误差是由这条线引起的:

    self.treeServiceSelection.handler = XmlHandler(self)

which passes an instance of Ui_MainWindow to the constructor for XmlHandler when it requires an instance of QTreeWidget. But as indicated previously, that is actually irrelevant, because all of the code that follows the first line is redundant anyway.

当它需要一个QTreeWidget实例时,它将一个Ui_MainWindow的实例传递给XmlHandler的构造函数。但如前所述,这实际上是不相关的,因为所有遵循第一行的代码都是多余的。

It seems that the more fundamental problem is that you are attempting to directly edit the ui file generated by pyuic instead of importing into your application. The generated ui file should be treated as read-only. Never, ever, be tempted to edit it.

看起来更基本的问题是,您试图直接编辑由pyuic生成的ui文件,而不是导入到应用程序中。生成的ui文件应该被视为只读的。永远不要被诱惑去编辑它。

Instead, you need to create a module containing a main window class that does something like this:

相反,您需要创建一个包含一个主窗口类的模块,该模块执行如下操作:

from ui import Ui_MainWindow

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        ui = Ui_MainWindow()
        ui.setupUi(self)
        # other setup code goes here
        ...

I would also suggest that you modify the MakeWidget class to something like this:

我还建议您将MakeWidget类修改为如下所示:

class MakeWidget(QtGui.QTreeWidget):
    def __init__(self, xml, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)

so that you can create an instance of it in MainWindow.__init__ like this:

这样就可以在主窗口中创建一个实例。__init__是这样的:

        self.treeServiceSelection = MakeWidget(xml, self)

or possibly factor the xml parsing code out into a method that takes the xml as an argument.

或者可能将xml解析代码分解成以xml作为参数的方法。

#1


1  

You create an instance of MakeWidget here:

在这里创建MakeWidget的实例:

    self.treeServiceSelection = MakeWidget()

which then sets up the XmlReader and so forth in its __init__. But, mysteriously, you then attempt to repeat it all in the following lines:

然后在其__init__中设置XmlReader等。但是,神秘地,你试图重复这一切在以下几行:

    self.treeServiceSelection.setHeaderLabels(['Servers and Services'])
    self.treeServiceSelection.source = QtXml.QXmlInputSource()
    self.treeServiceSelection.source.setData(xml)
    ...

What are you trying do here? If you need to adjust the initialization of the MakeWidget class, modify the code in its __init__.

你在这里做什么?如果需要调整MakeWidget类的初始化,请修改其__init__中的代码。

The actual error is caused by this line:

实际误差是由这条线引起的:

    self.treeServiceSelection.handler = XmlHandler(self)

which passes an instance of Ui_MainWindow to the constructor for XmlHandler when it requires an instance of QTreeWidget. But as indicated previously, that is actually irrelevant, because all of the code that follows the first line is redundant anyway.

当它需要一个QTreeWidget实例时,它将一个Ui_MainWindow的实例传递给XmlHandler的构造函数。但如前所述,这实际上是不相关的,因为所有遵循第一行的代码都是多余的。

It seems that the more fundamental problem is that you are attempting to directly edit the ui file generated by pyuic instead of importing into your application. The generated ui file should be treated as read-only. Never, ever, be tempted to edit it.

看起来更基本的问题是,您试图直接编辑由pyuic生成的ui文件,而不是导入到应用程序中。生成的ui文件应该被视为只读的。永远不要被诱惑去编辑它。

Instead, you need to create a module containing a main window class that does something like this:

相反,您需要创建一个包含一个主窗口类的模块,该模块执行如下操作:

from ui import Ui_MainWindow

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        ui = Ui_MainWindow()
        ui.setupUi(self)
        # other setup code goes here
        ...

I would also suggest that you modify the MakeWidget class to something like this:

我还建议您将MakeWidget类修改为如下所示:

class MakeWidget(QtGui.QTreeWidget):
    def __init__(self, xml, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)

so that you can create an instance of it in MainWindow.__init__ like this:

这样就可以在主窗口中创建一个实例。__init__是这样的:

        self.treeServiceSelection = MakeWidget(xml, self)

or possibly factor the xml parsing code out into a method that takes the xml as an argument.

或者可能将xml解析代码分解成以xml作为参数的方法。