QStandardItemModel 的 setData、setItemData 和 setIem 方法有什么区别?



我很困惑如何使用QStandardItemModel的setData、setItemData和setItem方法,这些方法似乎效果相同,我想知道我应该选择哪种方法最好?

class DemoD(QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
table = QTableView()
model = QStandardItemModel(4, 2)
table.setModel(model)
# delegate = SpinBoxDelegate()
# table.setItemDelegate(delegate)
for row in range(4):
for col in range(2):
item = QStandardItem('china')
model.setItem(row, col, item)
index = model.index(row, col)
value = QVariant((row + 1)*(col + 1))
model.setData(index, value)
model.setItemData(index, {1: 'a', 2: 'b'})
self.setCentralWidget(table)
self.resize(400, 300)
app = QApplication([])
demo = DemoD()
demo.show()
app.exec()

如果你想了解Qt模型的概念,你应该阅读以下指南:

  • 模型/视图编程
  • 模型/视图教程
  • Qt为什么滥用模型/视图术语
  • 每个方法的文档:setData((、setItemData((和setItem((

以前的概念:

  • QStandarItemModel:它是一个继承自QAbstractItemModel的类,允许存储任何类型的信息,而不是只定义行为的QAbstract ItemModel

考虑到您已经仔细阅读了前面的链接,我们将尝试解释您指示的不同方法之间的差异:

  • setData((:每个Qt模型都继承自QAbstractItemModel,因此该类定义了一般行为,在这种情况下,它定义了setData(((模型负责修改与QModelIndex关联的角色的信息。换句话说,如果你想实现一个可编辑的模型,它是你必须实现的通用方法,例如QStringListModel不是一个可编译的模型,所以它不实现它,但在QStandardItemModel的情况下,它是可编辑的,所以你可以通过该方法修改模型的信息。

  • setItem((:QStandardItem是QStandardItemModel的一个概念,在概念上类似于QModelIndex。此元素允许您轻松地与QModelIndex交互。如果QStandardItem与模型不关联,它将只存储信息,在分配模型时,所有信息都会传递给模型,并且模型会通知您可以通过其他方法(如setData(进行的任何更改。与模型的setData等效的是QStandardItem的setData方法,但后者不需要提供QModelIndex,因为该信息在内部可用,或者可以在建立模型时获得。

例如:

it.setText("foo")
it.setTextAlignment(QtCore.Qt.AlignCenter)

相当于

it.model().setData(it.index(), "foo", QtCore.Qt.DisplayRole)
it.model().setData(it.index(), QtCore.Qt.AlignCenter, QtCore.Qt.TextAlignmentRole)

正如您所看到的,QStandardItem允许您以简单的方式修改项目的信息,并且通过简单的方式您可以说它是模型的一个项目。

  • setItemData((:它是一种方法,允许您通过检查角色是否有效来修改与QModelIndex关联的多个角色的信息,通常,如果使用无效的模型,该方法将不会更新信息,但在处理通用信息的QStandardItemModel的情况下,已确定所有Role对于始终有效的内容都是有效的

在QStandardItemModel的情况下,以下代码是等效的:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
model = QtGui.QStandardItemModel(1, 1)
it = QtGui.QStandardItem()
model.setItem(0, 0, it)
# The following lines modify the text shown
# to be related to the Qt::DisplayRole role and
# the QModelIndex associated with the QStandardItem:
it.setText("foo")
it.setData("foo", QtCore.Qt.DisplayRole)
model.setData(it.index(), "foo", QtCore.Qt.DisplayRole)
model.setItemData(it.index(), {QtCore.Qt.DisplayRole: "foo"})
# The same as the previous lines but in the case of
# the background and the text colors of the item.
it.setForeground(QtGui.QColor("red"))
it.setBackground(QtGui.QColor("blue"))
it.setData(QtGui.QColor("red"), QtCore.Qt.ForegroundRole)
it.setData(QtGui.QColor("blue"), QtCore.Qt.BackgroundRole)
model.setData(it.index(), QtGui.QColor("red"), QtCore.Qt.ForegroundRole)
model.setData(it.index(), QtGui.QColor("blue"), QtCore.Qt.BackgroundRole)
model.setItemData(
it.index(),
{
QtCore.Qt.ForegroundRole: QtGui.QColor("red"),
QtCore.Qt.BackgroundRole: QtGui.QColor("blue"),
},
)

setDatasetItemData非常相似。

您必须理解的是,Qt模型使用角色将特定数据分配给每个"索引"。这意味着每个索引(对模型行和列的引用,如果模型支持树,则可能包括父索引(都可以附加不同的数据。最常用的数据角色是"DisplayRole",这是项视图通常显示为文本的内容;但通常会实现其他数据(参见ItemDataRole,这有助于项目视图向用户正确显示模型数据。

setDatasetItemData之间最重要的区别在于映射。您所做的操作不起作用,因为您使用的关键字未被识别为可用角色
在您的示例({1: 'a', 2: 'b'}(中,1映射到DecorationRole(在项目视图中用于显示装饰-图标(,2映射到EditRole,每当用户想要编辑该项目的内容时都会使用,可能与显示的内容不同(考虑以"10/11"等简短形式输入日期,这可能是最终显示为"2019年11月10日"的实际日期(。

最后,setItem是QStandardItemModel的一个特殊函数,它使用新提供的QStandardItem对象创建一个新项(或覆盖现有项(。

我提供了一个测试示例,它将更好地展示在这三种情况下会发生什么。

from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.table = QtWidgets.QTableView()
layout.addWidget(self.table)
# hide headers, we're not interested
self.table.horizontalHeader().setVisible(False)
self.table.verticalHeader().setVisible(False)
self.table.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
self.model = QtGui.QStandardItemModel()
self.table.setModel(self.model)
for item in range(1, 6):
item = QtGui.QStandardItem('item {}'.format(item))
self.model.appendRow(item)
toolLayout = QtWidgets.QHBoxLayout()
layout.addLayout(toolLayout)
self.itemTextEdit = QtWidgets.QLineEdit('text')
toolLayout.addWidget(self.itemTextEdit)
self.itemSetTextButton = QtWidgets.QPushButton('Set text')
toolLayout.addWidget(self.itemSetTextButton)
self.itemSetTextButton.clicked.connect(self.setText)
toolLayout.addSpacing(5)
self.itemAlignCombo = QtWidgets.QComboBox()
toolLayout.addWidget(self.itemAlignCombo)
for alignText in ('Left', 'Center', 'Right'):
alignment = QtCore.Qt.AlignVCenter | getattr(QtCore.Qt, 'Align{}'.format(alignText))
self.itemAlignCombo.addItem(alignText, alignment)
self.itemSetAlignButton = QtWidgets.QPushButton('Set alignment')
toolLayout.addWidget(self.itemSetAlignButton)
self.itemSetAlignButton.clicked.connect(self.setAlignment)
self.table.setCurrentIndex(self.model.index(0, 0))
toolLayout.addSpacing(5)
self.setDataButton = QtWidgets.QPushButton('SetItemData()')
toolLayout.addWidget(self.setDataButton)
self.setDataButton.clicked.connect(self.setItemData)
setItemLayout = QtWidgets.QHBoxLayout()
layout.addLayout(setItemLayout)
self.itemRowSpin = QtWidgets.QSpinBox()
setItemLayout.addWidget(self.itemRowSpin)
self.itemRowSpin.setRange(1, self.model.rowCount() + 1)
self.itemRowSpin.setValue(self.itemRowSpin.maximum())
self.setItemButton = QtWidgets.QPushButton('SetItem()')
setItemLayout.addWidget(self.setItemButton)
self.setItemButton.clicked.connect(self.setItem)
def setText(self):
# set the text of the current item
index = self.table.currentIndex()
self.model.setData(index, self.itemTextEdit.text())
def setAlignment(self):
# set the alignment of the current item
index = self.table.currentIndex()
self.model.setData(index, self.itemAlignCombo.currentData(), QtCore.Qt.TextAlignmentRole)
def setItemData(self):
# set *both* text and alignment of the current item
index = self.table.currentIndex()
self.model.setItemData(index, {
QtCore.Qt.DisplayRole: self.itemTextEdit.text(), 
QtCore.Qt.TextAlignmentRole: self.itemAlignCombo.currentData()
})
def setItem(self):
# set a new item for the selected row with the selected text and alignment
item = QtGui.QStandardItem()
item.setText(self.itemTextEdit.text())
item.setTextAlignment(QtCore.Qt.Alignment(self.itemAlignCombo.currentData()))
self.model.setItem(self.itemRowSpin.value() - 1, 0, item)
self.itemRowSpin.setMaximum(self.model.rowCount() + 1)
self.itemRowSpin.setValue(self.itemRowSpin.maximum())

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())

相关内容

  • 没有找到相关文章

最新更新