【问题标题】:QStandardItem.setText(QString) has unexpected type 'QVariant'?QStandardItem.setText(QString) 有意外的类型“QVariant”?
【发布时间】:2015-06-24 05:56:54
【问题描述】:

我在here学习了一个例子(由neuronet编写)。我尝试在QTableView中使用这种方法,但是当我更改文本时,会出现这样的错误

TypeError:QStandardItem.setText(QString):参数 1 具有意外类型“QVariant”。

一旦我按下“撤消”按钮,错误将是

TypeError: 'instancemethod' 对象未连接

这是我的代码,谢谢帮助。

# coding:utf-8
# coding:utf-8
from PyQt4 import QtGui, QtCore
import sys
class CommandTextEdit(QtGui.QUndoCommand):
    def __init__(self, table, item, oldText, newText, description):
        QtGui.QUndoCommand.__init__(self, description)
        self.item = item
        self.table = table
        self.oldText = oldText
        self.newText = newText

    def redo(self):
        self.item.model().itemDataChanged.disconnect(self.table.itemDataChangedSlot)
        self.item.setText(self.newText)
        self.item.model().itemDataChanged.connect(self.table.itemDataChangedSlot)

    def undo(self):
        self.item.model().itemDataChanged.disconnect(self.table.itemDataChangedSlot)
        self.item.setText(self.oldText)
        self.item.model().itemDataChanged.connect(self.table.itemDataChangedSlot)

class StandardItemModel(QtGui.QStandardItemModel):
    itemDataChanged = QtCore.pyqtSignal(object, object, object, object)

class StandardItem(QtGui.QStandardItem):
    def setData(self, newValue, role=QtCore.Qt.UserRole + 1):
        if role == QtCore.Qt.EditRole:
            oldValue = self.data(role)
            QtGui.QStandardItem.setData(self, newValue, role)
            model = self.model()
            #only emit signal if newvalue is different from old
            if model is not None and oldValue != newValue:
                model.itemDataChanged.emit(self, oldValue, newValue, role)
            return True
        QtGui.QStandardItem.setData(self, newValue, role)
class undoTable(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent = None)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.view = QtGui.QTableView()
        self.model = self.createModel()
        self.view.setModel(self.model)
        self.undoStack = QtGui.QUndoStack(self)
        undoView = QtGui.QUndoView(self.undoStack)
        buttonLayout = self.buttonSetup()
        mainLayout = QtGui.QHBoxLayout(self)
        mainLayout.addWidget(undoView)
        mainLayout.addWidget(self.view)
        mainLayout.addLayout(buttonLayout)
        self.setLayout(mainLayout)
        self.makeConnections()
    def createModel(self):
        model = StandardItemModel(4,4)
        for row in range(4):
            for column in range(4):
                item=StandardItem("(%s,%s)" % (row,column))
                model.setItem(row,column,item)
        return model

    def buttonSetup(self):
        self.undoButton = QtGui.QPushButton("Undo")
        self.redoButton = QtGui.QPushButton("Redo")
        self.quitButton = QtGui.QPushButton("Quit")
        buttonLayout = QtGui.QVBoxLayout()
        buttonLayout.addStretch()
        buttonLayout.addWidget(self.undoButton)
        buttonLayout.addWidget(self.redoButton)
        buttonLayout.addStretch()
        buttonLayout.addWidget(self.quitButton)
        return buttonLayout
    def itemDataChangedSlot(self, item, oldValue, newValue, role):
        if role == QtCore.Qt.EditRole:
            command = CommandTextEdit(self, item, oldValue, newValue,
                "Text changed from '{0}' to '{1}'".format(oldValue, newValue))
            self.undoStack.push(command)
            return True
    def makeConnections(self):
        self.model.itemDataChanged.connect(self.itemDataChangedSlot)
        self.quitButton.clicked.connect(self.close)
        self.undoButton.clicked.connect(self.undoStack.undo)
        self.redoButton.clicked.connect(self.undoStack.redo)

def main():
    app = QtGui.QApplication(sys.argv)
    newtable = undoTable()
    newtable.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

【问题讨论】:

标签: python qt pyqt pyside


【解决方案1】:

来自PyQt documentation

Qt 使用 QVariant 类作为任何 C++ 数据类型的包装器。 PyQt4 允许将任何 Python 对象包装为 QVariant 并传递 Qt 的元对象系统与任何其他类型一样。

PyQt4 将尝试将 Python 对象转换为 C++ 等价物,如果它 可以使 QVariant 可以传递给其他不支持的 C++ 代码 知道 Python 对象是什么。

PyQt4 的 QVariant API 版本 2 将自动转换 QVariant 返回到正确类型的 Python 对象。

QVariant API 的第 1 版提供了 QVariant.toPyObject() 将 QVariant 转换回正确的 Python 对象的方法 输入。

如果不能转换,两个版本都会引发 Python 异常 完成。

我猜您使用的是 Python 2.x,并且 PyQt 默认使用 QVariant API 的版本 1。 这意味着QVariant 不会自动转换为另一种类型(这里是QString),所以你会得到一个TypeError

所以,三个解决方案:

  • 使用 Python 3.x,默认情况下您将拥有 QVariant 版本 2

  • 在导入 PyQt 之前用 sip 更改 QVariant 的版本

    import sip
    sip.setapi('QVariant',2)
    from PyQt4 import QtGui, QtCore
    
  • 使用QVariant.toPyObject() 转换为正确的类型

    self.item.setText(self.newText.toString())
    

纠正后,我在您的代码中发现了另一个错误:

TypeError: invalid result type from StandardItem.setData()

这是因为你在setData() 中执行return True,它应该返回void(所以在Python 中,应该什么都不返回)

【讨论】:

  • 如此详细和准确!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多