目标:在Windows 7、10下的Qt5 C ++应用程序中拥有可滚动的自定义窗口小部件列表,数量达数千(甚至更多)。
问题:将窗口最小化到任务栏并再次还原后,程序停止响应。它不会崩溃。CPU使用率常数为25%。即使等待了几分钟,GUI也没有再次响应。此外,大量的内存被一般消费(超过200米),我认为这是太多甚至100K QLabels(近似2K每QLabel)。
以下是针对类似问题的一些建议解决方案,我认为这种解决方案不适合我的情况。
示例:以下示例说明了该问题。为了演示起见,使用了QLabels列表,但是它可以是从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
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
我有一些坏消息和一些好消息:
坏消息:您不能直接使用Qt Widgets执行此操作。
好消息:有一种方法可以做到,这与列表中的项数(数十亿)无关,但是您需要给自己一些时间来学习如何执行此操作。
所以,第一件事:QScrollArea并不是这样做的方法。正确的方法是使用Model / View / Controller编程范例。具有要显示的信息的数据模型必须与视图完全分开,以便Qt仅担心显示用户尝试查看的项目。想想看:如果您要在列表中放入十亿个元素,这是否意味着用户必须一次查看所有元素?这是否意味着Qt必须全部渲染?在您的代码中,这就是您要Qt执行的操作。你惊讶它慢吗?
建议。1:阅读Qt如何管理Model / View编程,然后选择正确的查看工具。我建议您使用QListView。如果您可以将东西放在表中,那么QTableView将使事情变得更容易。
列表上的控件是通过委托完成的。委托是负责在视图中绘制小部件的类。默认值是文本还是图标。
建议。2:忘了为每个元素创建Qt小部件。我刚刚回答了另一个人的问题,即为什么即使使用委托也无法解决问题。看一下Qt Torrent示例,看看那里是如何绘制控件的。
您可以做的是绘制控件,而不是小部件。这是因为您创建的每个小部件都必须转到Qt中的主事件循环,这会使您的程序变慢(并且您已经体验到了)。如果您从一圈到一圈只增加数字,将花费大量时间。您是否真的希望Qt的事件循环遍历所有小部件以处理其中的每个小部件?
建议。3:从简单开始!您似乎有很多事要做。从模型/视图开始,然后添加将绘制自定义控件的委托,然后将其展开。给自己时间去学习所有这一切。
祝好运!
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |