I have a variable like a
in the code below that has a lot of data. I want to show this data in a QListWidget or QListView. I have been using QListWidget, but it consumes more memory than QListView, so I have chosen QListView.
But in the code below, the speed of showing QListView is slower than QListWidget. Is there any way to solve this problem?
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_()
Output on my PC is:
show1 5.374950885772705
show2 1.3125648498535156
The difference is that the list-widget creates all the items in C++, whereas the list-view must make millions of Python method calls in your custom model. A flat, single-column tree-view is about twice as fast a list-view - but that's still significantly slower than the list-widget. For better performance, you could try implementing fetchmore. But this has the drawback of very slow scrolling, and you cannot easily navigate around the list (e.g. go straight to the last item). It also makes sorting and filtering much harder to implement.
If your data-set really is just a flat list of strings, you can achieve much better performance by using a QStringListModel. This is because it's much simpler than the item-based model used by list-widget (and of course, it's implemented in C++, unlike your custom model). If I add the following code to your test script:
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)
I get this output on my system:
show1 2.2652294635772705
show2 0.4205465316772461
show3 0.10054779052734375
So the stringlist-model is over four times faster than the list-widget in that scenario. However, if your actual requirements are more complex than that, you should probably consider using a database with an sql-based model.