В чем разница setData, setItemData и setIem метод QStandardItemModel? - PullRequest
2 голосов
/ 11 ноября 2019

Я запутался, как использовать setData , setItemData и setItem метод QStandardItemModel, эти методы, кажется, имеют тот же эффект, интересно знатькакой метод я должен выбрать для использования будет лучше?

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()

Ответы [ 2 ]

3 голосов
/ 11 ноября 2019

Если вы хотите понять концепции модели Qt, вам следует прочитать следующие руководства:

Предыдущие концепции:

  • QStandarItemModel : Этокласс, который наследуется от QAbstractItemModel, который позволяет хранить информацию любого типа, отличную от QAbstractItemModel, которая определяет только поведение.

Учитывая, что вы внимательно прочитали предыдущие ссылки, мы попытаемся объяснить разницу между различнымиуказанные вами методы:

  • setData (): Каждая модель Qt наследуется от QAbstractItemModel, поэтому этот класс определяет общее поведение, в данном случаеопределено, что модель setData ()спонсор для изменения информации роли, связанной с QModelIndex. Другими словами, это универсальный метод, который необходимо реализовать, если вы хотите реализовать редактируемую модель, например, QStringListModel не является редактируемой моделью, поэтому она не реализует ее, но в случае QStandardItemModel она редактируема, поэтому вы можете изменитьинформация о модели этого метода.

  • setItem (): QStandardItem - это концепция QStandardItemModel, концептуально похожая на QModelIndex,Этот элемент позволяет вам легко взаимодействовать с QModelIndex. Если QStandardItem не связан с моделью, он будет хранить только информацию, во время назначения модели вся информация передается модели, и модель информирует вас о любых изменениях, которые могут быть сделаны другими методами, такими как setData. Эквивалентом setData модели является метод setData класса QStandardItem, но последний не должен предоставлять 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, который обрабатывает общую информацию, установлено, что все роли действительны для того, что будетвсегда работает.

В случае 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"),
        },
    )
2 голосов
/ 11 ноября 2019

И 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_())
...