QStandardItem.setText(QString) 具有意外类型 'QVariant'?
QStandardItem.setText(QString) has unexpected type 'QVariant'?
我在学习了一个例子(neuronet写的),我尝试在QTableView中使用这个方法,但是当我更改文本时,会出现这样的错误
TypeError: QStandardItem.setText(QString): 参数 1 具有意外类型 'QVariant'.
一旦我按下 'undo' 按钮,错误将是
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()
Qt uses the QVariant class as a wrapper for any C++ data type. PyQt4
allows any Python object to be wrapped as a QVariant and passed around
Qt’s meta-object system like any other type.
PyQt4 will try to convert the Python object to a C++ equivalent if it
can so that the QVariant can be passed to other C++ code that doesn’t
know what a Python object is.
Version 2 of PyQt4’s QVariant API will automatically convert a
QVariant back to a Python object of the correct type.
Version 1 of the QVariant API provides the QVariant.toPyObject()
method to convert the QVariant back to a Python object of the correct
type.
Both versions will raise a Python exception if the conversion cannot
be done.
我猜你在 Python 2.x,并且 PyQt 默认使用 QVariant API 的版本 1。
这意味着 QVariant
不会自动转换为另一种类型(这里是 QString
),所以你得到 TypeError
.
所以,三个解决方案:
使用Python3.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
,这应该是 return void
(所以在 Python 中,应该是 return 没什么)
我在
TypeError: QStandardItem.setText(QString): 参数 1 具有意外类型 'QVariant'.
一旦我按下 'undo' 按钮,错误将是
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()
Qt uses the QVariant class as a wrapper for any C++ data type. PyQt4 allows any Python object to be wrapped as a QVariant and passed around Qt’s meta-object system like any other type.
PyQt4 will try to convert the Python object to a C++ equivalent if it can so that the QVariant can be passed to other C++ code that doesn’t know what a Python object is.
Version 2 of PyQt4’s QVariant API will automatically convert a QVariant back to a Python object of the correct type.
Version 1 of the QVariant API provides the QVariant.toPyObject() method to convert the QVariant back to a Python object of the correct type.
Both versions will raise a Python exception if the conversion cannot be done.
我猜你在 Python 2.x,并且 PyQt 默认使用 QVariant API 的版本 1。
这意味着 QVariant
不会自动转换为另一种类型(这里是 QString
),所以你得到 TypeError
.
所以,三个解决方案:
使用Python3.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
,这应该是 return void
(所以在 Python 中,应该是 return 没什么)