【问题标题】:Why is QListView slower than QListWidget?为什么 QListView 比 QListWidget 慢?
【发布时间】:2019-12-18 00:25:57
【问题描述】:

我在下面的代码中有一个像a 这样的变量,它有很多数据。我想在 QListWidget 或 QListView 中显示这些数据。我一直在使用QListWidget,但是它比QListView消耗更多的内存,所以我选择了QListView。

但是在下面的代码中,显示QListView的速度比QListWidget慢。有什么办法可以解决这个问题吗?

from PyQt5 import QtCore, QtGui, QtWidgets

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import time
app=QApplication([])
n=1000000

a=[]
for i in range(n):
     a.append('asfghjkg'+str(i))
class TodoModel(QtCore.QAbstractListModel):
    def __init__(self, todos=None):
        super(TodoModel, self).__init__()
        self.todos = todos or []

    def data(self, index, role):
        if role == Qt.DisplayRole:
            # See below for the data structure.
            return self.todos[index.row()]
            # Return the todo text only.

    def rowCount(self, index): 
        return len(self.todos)    


todos = a
model = TodoModel(todos)

t=time.time()
win1=QListView()
win1.setUniformItemSizes(True)
win1.setViewMode(1)
win1.setWrapping(False)
win1.setFlow(QListWidget.TopToBottom)
win1.setModel(model)
win1.show()
print('show1',time.time()-t)
t=time.time()
win2=QListWidget()
win2.setUniformItemSizes(True)
win2.addItems(a)
win2.show()
print('show2',time.time()-t)
app.exec_()

我的电脑上的输出是:

show1 5.374950885772705
显示2 1.3125648498535156

【问题讨论】:

  • 这不是一个很好的分析方法。使用python -m cProfile -s cumtime yourcode.py 之类的代码运行您的代码,您将看到时间都花在了哪里。请注意,它不仅存在于上述对rowCountlen 的数百万次调用中。

标签: python performance pyqt5 qlistwidget qlistview


【解决方案1】:

不同之处在于列表小部件在 C++ 中创建所有项目,而列表视图必须在您的自定义模型中进行数百万次 Python 方法调用。扁平的单列树形视图的速度大约是列表视图的两倍——但这仍然比列表小部件慢得多。为了获得更好的性能,您可以尝试实现fetchmore。但这具有滚动速度非常慢的缺点,并且您无法轻松地在列表中导航(例如,直接转到最后一项)。它还使排序和过滤更难实现。

如果您的数据集真的只是一个简单的字符串列表,您可以使用QStringListModel 获得更好的性能。这是因为它比 list-widget 使用的基于项目的模型要简单得多(当然,它是用 C++ 实现的,与您的自定义模型不同)。如果我将以下代码添加到您的测试脚本中:

model2 = QStringListModel(todos)
t=time.time()
win3=QListView()
win3.setUniformItemSizes(True)
win3.setViewMode(1)
win3.setWrapping(False)
win3.setFlow(QListWidget.TopToBottom)
win3.setModel(model2)
win3.show()
print('show3',time.time()-t)

我在我的系统上得到这个输出:

show1 2.2652294635772705
show2 0.4205465316772461
show3 0.10054779052734375

因此,在这种情况下,stringlist-model 比 list-widget 快四倍多。但是,如果您的实际需求比这更复杂,您可能应该考虑使用带有sql-based model 的数据库。

【讨论】:

  • 您能否评论一下“平面树视图应该比列表视图快 - 但它仍然会比列表小部件慢。”?为什么平面树视图比列表视图更快?为什么列表视图比列表小部件更快?该声明的什么意思适用于 c++ qt?以及如何/为什么对于 python Qt 是正确的?树木与这有什么关系?
  • 需要一种更可靠的方法来衡量性能。请注意,交换 OP 代码中的 win1 和 win2 部分不会导致它们的时间配置文件的简单交换。
  • 没有子项的单列树视图完全等同于列表视图。我使用相同的脚本对其进行了测试,当同时使用自定义模型和字符串列表模型时,它的速度大约是列表视图的两倍。树视图必须以不同的方式实现,因为它只使用自定义模型进行大约一半的 python 方法调用。带有字符串列表模型的列表视图比列表小部件更快,因为列表小部件使用基于项目的模型,效率较低(例如,它消耗更多内存)。
  • @ekhumoro 你的方法是个好主意,但它使用的内存几乎是纯 QList 视图模型的两倍。
  • @hpaalm 您是否尝试过将字符串直接添加到模型中,而不是先创建单独的列表?如果这没有任何区别,我想您只需要接受权衡:更快的速度 == 更多的内存。
猜你喜欢
  • 2011-08-25
  • 2011-03-23
  • 2015-10-04
  • 2012-09-16
  • 2016-10-06
  • 2020-11-27
  • 2011-10-19
  • 2020-12-24
  • 2010-11-05
相关资源
最近更新 更多