如何在Qt C+中显示大量小部件作为项目的可滚动列表+;应用程序? 目标:在Windows 7, 10下的QT5 C++应用程序中有一个可定制的小部件列表,它的数量为数千个(可能更多)。

如何在Qt C+中显示大量小部件作为项目的可滚动列表+;应用程序? 目标:在Windows 7, 10下的QT5 C++应用程序中有一个可定制的小部件列表,它的数量为数千个(可能更多)。,c++,windows,qt,qt5,C++,Windows,Qt,Qt5,问题:最小化任务栏窗口并再次恢复后,程序停止响应。但它没有崩溃。CPU使用率为25%。即使等待几分钟,GUI也不会再次响应。此外,通常会消耗大量内存(超过2亿),我认为即使对于10万个QLabel(每个QLabel大约2千个),这也太多了 以下是一些针对类似问题的建议解决方案,我认为这些方案不适合我的情况 示例:以下示例说明了该问题。为了演示,使用了QLabel列表,但它可以是从QWidget派生的任何类 main window.h #ifndef MAINWINDOW_H #define MA

问题:最小化任务栏窗口并再次恢复后,程序停止响应。但它没有崩溃。CPU使用率为25%。即使等待几分钟,GUI也不会再次响应。此外,通常会消耗大量内存(超过2亿),我认为即使对于10万个QLabel(每个QLabel大约2千个),这也太多了

以下是一些针对类似问题的建议解决方案,我认为这些方案不适合我的情况

示例:以下示例说明了该问题。为了演示,使用了QLabel列表,但它可以是从QWidget派生的任何类

main window.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
\ifndef主窗口
#定义主窗口
#包括
#包括
#包括
#包括
类主窗口:公共QMainWindow
{
Q_对象
公众:
显式主窗口(QWidget*parent=0);
};
#endif//main窗口
main window.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);
}
#包括“MainWindow.h”
MainWindow::MainWindow(QWidget*parent):QMainWindow(parent)
{
QScrollArea*scrollArea=新的QScrollArea(本);
QFrame*frame=新QFrame();
QVBoxLayout*l=新的QVBoxLayout(框架);
int N=121004;
scrollArea->setWidget(框架);
scrollArea->SetWidgetResizeable(真);
对于(intn=0;naddWidget(新的QLabel(QString::number(n,this));}
调整大小(640480);
setCentralWidget(滚动区域);
}

我有一些坏消息和一些好消息:

坏消息是:您不能直接使用Qt小部件执行此操作

好消息:有一种方法可以做到这一点,它与列表中的项目数量无关(甚至数十亿),但你需要给自己时间来学习如何做到这一点

所以,第一件事:QScrollArea不是这样做的。正确的方法是使用。包含要显示的信息的数据模型必须与视图完全分离,这样Qt就只需要担心显示用户试图查看的项目。想想看:如果你有10亿个元素要放在这个列表中,这是否意味着用户必须一次看到它们?这是否意味着Qt必须将它们全部渲染?在您的代码中,这就是您要求Qt执行的操作。你对它的速度慢感到惊讶吗

第1条建议:阅读Qt如何管理,然后选择正确的查看工具。我建议按照你的描述。如果你能把东西放在桌子上,会让事情变得更容易

列表上的控制是通过委托完成的。委托是负责在视图中绘制小部件的类。默认情况下,将只执行文本与图标的比较

第2条建议:忘记为每个元素创建Qt小部件。关于为什么这不起作用,即使在使用代理时也是如此。看一看,看看控件是如何在那里绘制的

您可以做的是绘制控件,而不是小部件。这是因为您创建的每个小部件都必须转到Qt中的主事件循环,这将使您的程序变慢(您已经经历过)。如果你只是为了增加数字而从1循环到100万,这将花费大量的时间。你真的想让Qt的事件循环遍历你所有的小部件来处理它们中的每一个吗

第3条建议:简单开始!你似乎有很多事情要做。从模型/视图开始,然后添加将绘制自定义控件的委托,然后将其展开。给自己时间去学习这一切


祝你好运

我实现了一个列表小部件,它可以显示数十亿个项目,每个项目具有任意数量的小部件,而不会出现任何性能问题。不幸的是,我不能分享代码

它是在
QAbstractScrollArea
之上实现的,不使用Qt的模型/视图框架。它只处理跟踪视图中项目的范围、对这些项目调用适当的绘图函数,以及跟踪所有组合项目的总体高度。就这样

每个项目都可能有一个关联的小部件。此小部件可能任意复杂。项目小部件在项目处于视图中时可见。在我的实现中,条目通常会延迟创建小部件,这就是为什么这样做很快的原因之一。例如,如果您有10亿个项目,那么只有一小部分项目会出现在视图中,因此花费任何精力为这些项目构建小部件都是一种浪费


由于每个项目都对其外观负责,因此在使用此类非常通用的列表小部件显示内容方面,这提供了很大的灵活性。

您是否查看了我提供的示例?创建小部件并在屏幕上呈现它们并不需要很多时间。这肯定比处理几个元素要慢,但这是在合理的时间内完成的。当窗口最小化到任务栏并再次恢复时,就会出现问题。然后,也只有到那时,重新绘制应用程序窗口才会花费很长时间。此外,在QListView显示的所有项目中都有一个按钮怎么样?@scopchanov是的,我看到了上面的代码。你必须明白,做事有正确的方法,也有无数其他错误的方法。Qt作为一个库和一个产品,以某种方式解决了每个问题。如果你把一些东西拼凑在一起,它就可以工作了,那对你有好处!但是你不能期望你渲染一个100k的元素,然后抱怨它太慢。再一次,你强迫你的Qt去做一些不该做的事情。即使它适用于此版本或计算机,或此操作系统,也可能不适用于其他版本或计算机。[…]@scopchanov现在开始绘制按钮,