【问题标题】:Calling a class to build a QTreeWidget within a Window: argument 1 has unexpected type 'Ui_MainWindow'调用类以在 Window 中构建 QTreeWidget:参数 1 具有意外类型“Ui_MainWindow”
【发布时间】:2013-11-04 19:28:47
【问题描述】:

我正在使用从ekhumoro 获得的代码从我创建的 GUI 的 xml 文件动态创建树,但是当尝试调用从 pyuic4 生成的 _ui.py 文件中的类时,我'正在返回 Ui_MainWindow 类而不是预期的参数。

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

使用 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)

我摸索着尝试在我的 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"))

以及我在尝试运行文件时遇到的错误:

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'

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

【问题讨论】:

    标签: python pyqt4 qtreewidget qtreewidgetitem qtxml


    【解决方案1】:

    您在此处创建MakeWidget 的实例:

        self.treeServiceSelection = MakeWidget()
    

    然后在其__init__ 中设置XmlReader 等等。但是,奇怪的是,您随后尝试在以下几行中重复这一切:

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

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

    实际错误是由这一行引起的:

        self.treeServiceSelection.handler = XmlHandler(self)
    

    当它需要QTreeWidget 的实例时,它将Ui_MainWindow 的实例传递给XmlHandler 的构造函数。但如前所述,这实际上是无关紧要的,因为第一行之后的所有代码无论如何都是多余的。

    似乎更根本的问题是您试图直接编辑 pyuic 生成的 ui 文件,而不是导入到您的应用程序中。生成的 ui 文件应被视为只读文件。永远不要试图编辑它。

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

    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
            ...
    

    我还建议您将 MakeWidget 类修改为如下内容:

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

    这样您就可以像这样在MainWindow.__init__ 中创建它的实例:

            self.treeServiceSelection = MakeWidget(xml, self)
    

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

    【讨论】:

    • 非常感谢!我今晚下班回家时会看看这个。我在这里的工作绝对是过于雄心勃勃,但我已经看到你在谈论重新遍历所有 XmlHandler 的东西。我想我最大的障碍是理解如何在标准库之外的另一个类中使用一个类。
    • ekh,不确定您是否会看到此更新,但我想如果可能的话,我可能会跳过问另一个问题。有没有办法返回项目的 isChecked 状态,以便我稍后可以在另一个函数中使用该数据(即按下按钮)?我一直在看 QTreeWidgetItemIterator 但看起来我可能需要制作一个自定义信号?
    • @Amdingo。它真的应该放在另一个问题中,以便其他人有机会回答。此外,您可能需要更清楚地解释您要做什么,并包含一些示例代码。
    • 会做的,非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2012-12-12
    • 2020-10-17
    • 2021-03-18
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多