首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >自定义IndexWidget在QListView中的平滑延迟加载和卸载

自定义IndexWidget在QListView中的平滑延迟加载和卸载
EN

Stack Overflow用户
提问于 2013-03-17 20:15:15
回答 2查看 2.5K关注 0票数 4

我正在编写一个应用程序,它使用自定义QWidget代替PyQt中的常规词条或委托。我遵循了Render QWidget in paint() method of QWidgetDelegate for a QListView中的答案--除其他外--用自定义小部件实现QTableModel。生成的示例代码位于此问题的底部。在实现方面存在一些问题,我不知道如何解决:

  1. 当没有显示项目时卸载它们。我计划为一个包含数千个条目的列表构建我的应用程序,而我不能将这么多的小部件保存在内存中。
  2. 加载尚未查看的项,或至少异步加载它们。小部件需要花一些时间来呈现,下面的示例代码在滚动列表时有一些明显的滞后。
  3. 当在下面的实现中滚动列表时,加载时新加载的每个按钮都会在QListView的左上角出现一秒,然后反弹到位置。如何才能避免这种情况?

--

代码语言:javascript
运行
复制
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt


class TestListModel(QtCore.QAbstractListModel):
    def __init__(self, parent=None):
        QtCore.QAbstractListModel.__init__(self, parent)
        self.list = parent

    def rowCount(self, index):
        return 1000

    def data(self, index, role):
        if role == Qt.DisplayRole:
            if not self.list.indexWidget(index):
                button = QtGui.QPushButton("This is item #%s" % index.row())
                self.list.setIndexWidget(index, button)
            return QtCore.QVariant()

        if role == Qt.SizeHintRole:
            return QtCore.QSize(100, 50)

    def columnCount(self, index):
        pass


def main():
    app = QtGui.QApplication(sys.argv)

    window = QtGui.QWidget()

    list = QtGui.QListView()
    model = TestListModel(list)

    list.setModel(model)
    list.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)

    layout = QtGui.QVBoxLayout(window)
    layout.addWidget(list)

    window.setLayout(layout)
    window.show()

    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
EN

回答 2

Stack Overflow用户

发布于 2013-03-21 13:20:52

您可以使用代理模型来避免加载所有小部件。代理模型可以用viewport和小部件的高度计算行计数。他可以用滚动条值计算项目的索引。

这是一个摇摇欲坠的解决方案,但应该有效。

如果使用以下方法修改data()方法:

代码语言:javascript
运行
复制
button = QtGui.QPushButton("This is item #%s" % index.row())
self.list.setIndexWidget(index, button)
button.setVisible(False)

这些项目将不会显示,直到他们被移动到他们的位置(它为我工作)。

票数 2
EN

Stack Overflow用户

发布于 2013-03-22 18:11:44

QTableView只为其视口中的项向模型请求数据,因此数据的大小不会真正影响速度。因为您已经对QAbstractListModel进行了子类化,所以您可以重新实现它,在初始化时只返回一小部分行,并修改它的canFetchMore方法,以便在未显示记录总数时返回True。尽管在数据大小的情况下,您可能想考虑创建一个数据库,而不是使用QSqlQueryModelQSqlTableModel,但它们都是在256个组中延迟加载的。

要获得更流畅的项目负载,您可以连接到valueChanged信号的QTableView.verticalScrollBar(),并且取决于它的valuemaximum之间的区别,有如下所示:

代码语言:javascript
运行
复制
while xCondition:
   if self.model.canFetchMore():
      self.model.fetchMore()

使用setIndexWidget会大大降低应用程序的速度。您可以使用QItemDelegate并自定义它的paint方法来显示按钮,如下所示:

代码语言:javascript
运行
复制
class MyItemDelegate(QtGui.QItemDelegate):
    def __init__(self, parent=None):
        super(MyItemDelegate, self).__init__(parent)

    def paint(self, painter, option, index):
        text = index.model().data(index, QtCore.Qt.DisplayRole).toString()

        pushButton = QtGui.QPushButton()
        pushButton.setText(text)
        pushButton.setGeometry(option.rect)

        painter.save()
        painter.translate(option.rect.x(), option.rect.y())

        pushButton.render(painter)

        painter.restore()

并将其设置为:

代码语言:javascript
运行
复制
myView.setItemDelegateForColumn(columnNumber, myItemDelegate)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15465677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档