qtpyqtlimitqlistwidget

Is there any limit to the number of items in a QListWidget?


I am writing a program using PyQt5.

Is there any limit to the number of items that can be added to a QListWidget?


Solution

  • If the view is populated on demand (with only a relatively small number of items being shown at once), there's no effective limit (as demonstrated by the Fetch More Example in the Qt docs). However, the number of items that can be displayed at the same time does have a fixed limit.

    This limit is determined by the size of a signed int (which is in turn determined by the compiler used to build the Qt libraries). For most systems, the size will be four bytes (but it could be 2 bytes for some embedded systems), which equates to 2,147,383,647 items.

    The size cannot be larger than this, because all models (including the internal one used by QListWidget) must be subclasses of QAbstractItemModel, which are required to return integer values from methods such as rowCount. If larger values are returned, an overflow-error will occur:

    import ctypes
    from PyQt5 import QtCore, QtWidgets
    
    MAXINT = 2 ** (8 * ctypes.sizeof(ctypes.c_int())) // 2 - 1
    
    class Model(QtCore.QAbstractListModel):
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if index.isValid() and role == QtCore.Qt.DisplayRole:
                return f'Item ({index.row()})'
    
        def rowCount(self, parent=None):
            return MAXINT + 1
    
    app = QtWidgets.QApplication(['Test'])
    view = QtWidgets.QListView()
    model = Model()
    print('row-count:', model.rowCount())
    view.setModel(model)
    view.show()
    app.exec()
    

    Output:

    row-count: 2147483648
    OverflowError: invalid result from Model.rowCount(), value must be in the range -2147483648 to 2147483647
    

    However, even if you restrict the number of items to less than this fixed limit, there's no guarantee that the view will be able to display them. During testing, I found that 10 thousand items would load almost instantly, 100 thousand took about 1-2 seconds, and 1 million about 20 seconds. But displaying 10 million items at once took over three minutes to load, and attempting to load more than about 500 million items resulted in an immediate segmentation fault.

    For a QListWidget, these timings would be much worse, since the cost of creating a QListWidgetItem adds a significant amount of overhead (and the same goes for QStandardItemModel). So long before you hit the fixed limit, performance considerations will demand that some kind of Fetch More approach will be required.