canFetchMore()和fetchMore()未按预期工作

时间:2017-01-16 19:54:38

标签: python qt pyqt pyside model-view

使用canFetchMore()fetchMore()延迟加载实现Qt树模型时遇到问题。我有这段代码:

from PySide.QtCore import Qt, QAbstractItemModel, QModelIndex
from PySide.QtWidgets import QTreeView, QApplication


BATCH_SIZE = 100


class ObjectItem(object):

    def __init__(self, parent, name, data, row):
        self.parent = parent
        self.name = name
        self.data = data
        self.row = row

        self.hasChildren = False
        self.canFetchMore = False

        # ints have no children
        if isinstance(data, int):
            return

        self.childCount = 0
        self.childItems = []

        if len(data) > 0:
            self.canFetchMore = True
            self.hasChildren = True

        self.childCount = len(self.childItems)
        if self.childCount > 0:
            self.hasChildren = True

    def fetchMore(self):
        loadedCount = len(self.childItems)
        totalCount = len(self.data)
        remainder = totalCount - loadedCount
        fetchCount = min(BATCH_SIZE, remainder)
        for _ in range(fetchCount):
            name = "[{}]".format(loadedCount)
            value = self.data[loadedCount]
            self.childItems.append(ObjectItem(self, name, value, loadedCount))
            loadedCount += 1
        self.canFetchMore = loadedCount < totalCount
        return fetchCount


class MyTreeModel(QAbstractItemModel):

    def __init__(self, data, parent=None):
        super(MyTreeModel, self).__init__(parent)
        self.rootItem = ObjectItem(None, "root", data, 0)
        self.headerLabels = ["Name", "Type", "Value"]

    def hasChildren(self, parent=QModelIndex()):
        return parent.internalPointer().hasChildren if parent.isValid() else True

    def rowCount(self, parent=QModelIndex()):
        return parent.internalPointer().childCount if parent.isValid() else 1

    def columnCount(self, parent=QModelIndex()):
        return 3

    def index(self, row, column, parent=QModelIndex()):
        if not parent.isValid():
            return self.createIndex(row, column, self.rootItem)

        parentItem = parent.internalPointer()
        return self.createIndex(row, column, parentItem.childItems[row])

    def parent(self, index):
        item = index.internalPointer()
        if item == self.rootItem:
            return QModelIndex()
        parentItem = item.parent
        return self.createIndex(parentItem.row, 0, parentItem)

    def data(self, index, role):
        item = index.internalPointer()
        if role == Qt.DisplayRole:
            if index.column() == 0:
                return item.name
            elif index.column() == 1:
                return item.data.__class__.__name__
            elif index.column() == 2:
                return repr(item.data)
        return None

    def headerData(self, index, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.headerLabels[index]
        return None

    def canFetchMore(self, parent=QModelIndex()):
        if parent.isValid():
            return parent.internalPointer().canFetchMore
        else:
            return False

    def fetchMore(self, parent=QModelIndex()):
        parentItem = parent.internalPointer()
        firstIndex = parentItem.childCount
        fetchedCount = parentItem.fetchMore()
        lastIndex = firstIndex + fetchedCount - 1
        self.beginInsertRows(parent, firstIndex, lastIndex)
        parentItem.childCount = len(parentItem.childItems)
        self.endInsertRows()

# test data
data = [list(range(1000)), list(range(1000))]

app = QApplication([])
view = QTreeView()
model = MyTreeModel(data)
view.setModel(model)
view.show()
app.exec_()

这可能是代码的最短版本(简化,未经优化,不够通用等),可以复制问题。我想显示listint s的树。请注意,在上面的示例中,我有两个listint s,每个int s包含1000个int s。但由于某些未知原因,当节点展开时以及滚动到最底部后,只有前300个from PySide.QtCore import Qt, QAbstractItemModel, QModelIndex from PySide.QtGui import QApplication, QTreeView BATCH_SIZE = 100 class LazyModel(QAbstractItemModel): def __init__(self, totalCount, parent=None): super(LazyModel, self).__init__(parent) self.items = [] self.totalCount = totalCount self.loadedCount = 0 def hasChildren(self, parent=QModelIndex()): if not parent.isValid(): return True else: return False def rowCount(self, parent=QModelIndex()): return self.loadedCount def columnCount(self, parent=QModelIndex()): return 2 def index(self, row, column, parent=QModelIndex()): return self.createIndex(row, column, None) def parent(self, index): return QModelIndex() def data(self, index, role): if role == Qt.DisplayRole: if index.column() == 0: return str(index.row()) else: return str(self.items[index.row()]) return None def canFetchMore(self, parent=QModelIndex()): return self.loadedCount < self.totalCount def fetchMore(self, parent=QModelIndex()): remainder = self.totalCount - self.loadedCount fetchCount = min(BATCH_SIZE, remainder) for i in range(fetchCount): self.items.append(len(self.items)) self.beginInsertRows(parent, self.loadedCount, self.loadedCount + fetchCount - 1) self.loadedCount += fetchCount self.endInsertRows() app = QApplication([]) view = QTreeView() model = LazyModel(10000) view.setModel(model) view.show() app.exec_() 被显示。我希望在我向下滚动时添加项目。但是,只有当我折叠并再次展开节点时才会添加它们。

换句话说,添加节点只是为了对父节点的折叠和扩展做出反应,而不是作为对滚动到底部的反应。

有什么问题?我忽略了什么吗?

更新:与第一个版本相比,我更加简化了代码。

UPDATE2:要将它与没有层次结构的模型进行比较,它按预期工作(当用户向下滚动时获取更多数据),请查看以下代码:

u

这是否意味着我的等级制度有问题?

0 个答案:

没有答案