И setData
, и setItemData
очень похожи.
Вы должны понять, что модели Qt используют роли для назначения определенных данных каждому "индексу". Это означает, что к каждому индексу (ссылка на строку и столбец модели, возможно, включая родительский элемент, если модель поддерживает деревья) могут быть привязаны разные данные. Наиболее часто используемая роль данных - это «DisplayRole
», которая обычно отображается в виде текста;но обычно используются другие данные (см. ItemDataRole
, что помогает представлению элемента правильно отображать данные модели для пользователя.
Наиболее важное различие между setData
и setItemData
является сопоставлением. То, что вы делаете, не работает, так как используемые вами ключевые слова не распознаются как пригодных для использования ролей.
В вашем примере ({1: 'a', 2: 'b'}
) 1
сопоставляется сDecorationRole
(который используется из представлений элементов для отображения украшения - значка) и 2
отображается на EditRole
, который используется всякий раз, когда пользователь хочет редактировать содержимое этого элемента, что может отличаться от из того, что отображается (подумайте о вводе даты в краткой форме, такой как «10/11», которая может быть фактической датой, которая окончательно отображается как «ноябрь 10 2019»).
Наконец,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_())