【问题标题】:QListView takes too long to update when given 100k items给定 100k 个项目时,QListView 更新时间过长
【发布时间】:2013-08-31 12:17:44
【问题描述】:

我在阅读文件时遇到问题,具体是我想制作一本小字典。在我需要阅读的文件中有这样的内容:

a   Ph  P6
a   snsr    CA
a b c   fb  Dj
a b c - book    i+  BS
A except B gate oOPa    y
a font  kQ  BU
[....]

它有大约 109.000 行,文件只有大约 2MB。在我的 QT 应用程序中,我这样编写代码来读取项目并将其添加到 QListWidget:

QString sWord;
QFile inFile("C:\\EV\\ev.index");

inFile.open(QIODevice::ReadOnly|QIODevice::Text);
QTextStream in(&inFile);
while(!in.atEnd())
{
     sWord = in.readLine();
     myListWidget->addItem(sWord); //myListWidget is a QListWidget
}

但它读得太长了!起初我认为原因是我的应用程序逐行读取,所以我再次编码如下:

QString data;
QStringList listWord;
QFile inFile("C:\\EV\\ev.index");


inFile.open(QIODevice::ReadOnly|QIODevice::Text);
QTextStream in(&inFile);
data.append(in.readAll());
listWord.append(data.split('\n'));
myListWidget->addItems(listWord);
inFile.close();

它运行得更快!(应用程序启动后大约 5 秒),仍然很长,我希望它阅读得更快。我该怎么办?

【问题讨论】:

    标签: qt


    【解决方案1】:
    1. 列表小部件的布局时间过长。将列表小部件的 uniformItemSizes 属性设置为 true。这避免了昂贵的布局操作。另一种方法是将layoutMode 属性设置为QListView::Batched。这避免了一次昂贵地布置所有项目。

    2. 如果QListView 的开销较低,请不要使用QListWidget

    3. 应批量添加大量元素,即不要将元素一个接一个地插入模型中。在只发出一次rowsInsertedcolumnsInserted 信号的原子操作中插入每个批次的元素。

    4. 您不得在 GUI 线程中执行任何文件加载。这是许多应用程序中糟糕的用户体验的根源,必须以大量的蔑视来阻止。 不要这样做

    下面是一个将所有这些都考虑在内的最小示例。

    // https://github.com/KubaO/stackoverflown/tree/master/questions/filemodel-18548048
    #include <QtWidgets>
    #include <QtConcurrent>
    
    void makeLines(QBuffer &buf, int count = 1000000) {
       buf.open(QIODevice::WriteOnly | QIODevice::Text);
       char line[16];
       for (int i = 0; i < count; ++i) {
          int n = qsnprintf(line, sizeof(line), "Item %d\n", i);
          buf.write(line, n);
       }
       buf.close();
    }
    
    struct StringListSource : QObject {
       Q_SIGNAL void signal(const QStringList &);
       void operator()(const QStringList &data) { emit signal(data); }
       Q_OBJECT
    };
    
    int main(int argc, char *argv[]) {
       QApplication app(argc, argv);
       QListView view;
       QStringListModel model;
       StringListSource signal;
       QObject::connect(&signal, &StringListSource::signal, &model, &QStringListModel::setStringList);
       QtConcurrent::run([&signal]{
          QBuffer file;
          signal({"Generating Data..."});
          makeLines(file);
          signal({"Loading Data..."});
          QStringList lines;
          if (file.open(QIODevice::ReadOnly | QIODevice::Text))
             while (!file.atEnd())
                lines.append(QString::fromLatin1(file.readLine()));
          file.close();
          signal(lines);
       });
       view.setModel(&model);
       view.setUniformItemSizes(true);
       view.show();
       return app.exec();
    }
    #include "main.moc"
    

    【讨论】:

    • 你救了我!根据您在第 1 项中的建议,我拨打了ui-&gt;listView-&gt;setUniformItemSizes(true) 的电话。我使用从QAbstractItemModel 派生的自定义模型向QListView 添加了大约150 万个项目,这需要几分钟。将 setUniformItemSizes 设置为 true 可将时间缩短到 1 秒以下。感谢您的提示!
    • 惊人的答案!谢谢你。我正在设计一个音乐库,所以同样的概念。打印从数据库文件中读取的 100,000 首歌曲的信息。我已经等待了大约 15 分钟来加载视图。
    猜你喜欢
    • 2011-07-08
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    相关资源
    最近更新 更多