что вызывает QTreeView для запроса SizeHintRole в функции QAbstractItemModel.data () - PullRequest
0 голосов
/ 01 ноября 2018

Я сделал несколько разных приложений, используя TreeViews и AbstractItemModels, но наткнулся на то, чего я не понимаю. Я понял, что представление вызывает функцию data модели, запрашивающую Size для элементов, поскольку роль была SizeHintRole (, см. Документацию Qt ). Во всех других случаях я никогда не вспоминаю о необходимости беспокоиться о возвращении size для функции data. В приведенном ниже коде я ошибочно ожидал, что data будет просто искать элементы в списке, и если вы раскомментируете первую строку, представление ничего не отображает, потому что на самом деле представление запрашивает sizeHint индексов .

Мой вопрос: какие обстоятельства требуют этого? Мне никогда не приходилось предоставлять sizeHint раньше, и я не понимаю, когда это требуется, а когда нет.

окно, когда закомментирована первая строка

enter image description here

окно, когда включена первая строка, поэтому игнорируйте запрос sizeHint

enter image description here

import sys
from PyQt5 import QtCore, QtWidgets

class TreeList:
    def __init__(self):
        self._items = list()

class TreeModel(QtCore.QAbstractItemModel):
    def __init__(self, root, parent=None):
        super().__init__(parent)
        self.root = root

    def index(self, row: int, column: int, parent: QtCore.QModelIndex = ...) -> QtCore.QModelIndex:
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()

        if not parent.isValid():
            pointer = self.root  # type: TreeList
            child = pointer._items[row]
        else:
            child = None

        return self.createIndex(row, column, child)

    def addItem(self, layer):
        row = len(self.root._items)
        self.beginInsertRows(QtCore.QModelIndex(), row, row)
        self.root._items.append(layer)
        self.endInsertRows()

    def parent(self, child: QtCore.QModelIndex) -> QtCore.QModelIndex:
        return QtCore.QModelIndex()

    def rowCount(self, parent: QtCore.QModelIndex = ...) -> int:
        if parent.isValid():
            return 0
        else:
            return len(self.root._items)

    def columnCount(self, parent: QtCore.QModelIndex = ...) -> int:
        return 1

    def hasChildren(self, parent: QtCore.QModelIndex = ...) -> bool:
        return False if parent.isValid() else True

    def data(self, index: QtCore.QModelIndex, role: int = ...):
        # return self.root._items[index.row()]
        if role == QtCore.Qt.SizeHintRole:
            print(index.isValid(), index.row(), index.column())
            return QtCore.QSize(100, 20)
        else:
            return self.root._items[index.row()]

    def flags(self, index: QtCore.QModelIndex):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable


class StackTreeView(QtWidgets.QTreeView):
    def __init__(self, data=None, parent=None):
        super().__init__(parent)
        self.setModel(TreeModel(data))

    def addItem(self, layer):
        self.model().addItem(layer)


def test():
    app = QtWidgets.QApplication(sys.argv)
    data = TreeList()
    data._items = ['one', 'two']
    sys.excepthook = sys.__excepthook__
    tree_view = StackTreeView(data)
    tree_view.show()
    tree_view.addItem('three')
    tree_view.addItem('four')
    sys.exit(app.exec_())


if __name__ == '__main__':
    test()

1 Ответ

0 голосов
/ 01 ноября 2018

Возвращение self.root._items[index.row()] по умолчанию для всех ролей вообще не имеет смысла. Вы должны всегда явно проверять роль и только когда-либо возвращать значение, подходящее для этой конкретной роли . Если у вас нет данных, специфичных для роли, вы должны вернуть None в PyQt (что эквивалентно неверному QVariant в C ++).

См. Справочник по подклассам моделей для ознакомления с основными требованиями.

...