How to display a scrollable list with a substantial amount of widgets as items in a Qt C++ app?

Viewed 5056

Goal: To have a scrollable list of custom widgets amounting hunderts of thousands (and possibly more) in a Qt5 C++ application under Windows 7, 10.

Problem: The program stops responding after minimizing the window to the task bar and restoring it again. It doesn't crash though. The CPU usage constants 25%. The GUI doesn't become responsive again even after several minutes of waiting. Furthermore, a large amount of memory is being consumed in general (more than 200M), which I think is too much even for 100k QLabels (aprox 2k per QLabel).

Here are some suggested solutions to a similar problem, which I don't find suitable for my case.

Example: The following example illustrates the problem. For the sake of the demonstration a list of QLabels is used, but it could be any class derived from QWidget.

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QLabel>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    QScrollArea *scrollArea = new QScrollArea(this);
    QFrame *frame = new QFrame();
    QVBoxLayout *l = new QVBoxLayout(frame);
    int N = 121004;

    scrollArea->setWidget(frame);
    scrollArea->setWidgetResizable(true);

    for (int n = 0; n < N; n++) { l->addWidget(new QLabel(QString::number(n), this)); }

    resize(640, 480);
    setCentralWidget(scrollArea);
}
2 Answers

I have implemented a list widget that can show billions of items with an arbitrary number of widgets per item without any performance issues. Unfortunately, I can not share the code.

It is implemented on top of QAbstractScrollArea, and does not use Qt's model/view framework. It only deals with keeping track of the range of items that are in view, calling the appropriate draw function on those items, and keeping track of the overall height of all items combined. That's it.

Every item may have one associated widget. This widget may be arbitrarily complex. Item widgets are made visible when the item is in view. In my implementation, items usually lazily create the widgets, which is one of the reasons why this is fast. In case you have a billion items for example, only a very small subset of those will ever be in view, so it would be a waste to spend any effort in constructing widgets for these items.

Since every item is responsible for the way it looks, this gives a lot of flexibility in terms of what is possible to display with such a very generic list widget.

Related