给定100k项目时,QListView需要很长时间才能更新

时间:2013-08-31 12:17:44

标签: qt

我有阅读文件的问题,具体是我想做一个小字典。在我需要阅读的文件中有如下内容:

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秒),仍然很长,我希望它读得更快。我该怎么办?

1 个答案:

答案 0 :(得分:7)

  1. 列表小部件的布局需要太长时间。将列表小部件的uniformItemSizes属性设置为true。这避免了昂贵的布局操作。另一种方法是将layoutMode属性设置为QListView::Batched。这样可以避免不必一次昂贵地布置所有物品。

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

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

  4. 您不能在GUI线程中执行任何文件加载。这是许多应用程序中糟糕的用户体验的来源,并且必须因为大量的嘲笑而气馁。 不要这样做

  5. 以下是考虑所有这些因素的最小示例。

    // 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"