Обновление QListView занимает слишком много времени, если дано 100 тыс. Элементов
У меня проблема с чтением файла, в частности, я хочу сделать небольшой словарь. В файле, который мне нужно прочитать, есть такой контент:
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 строк, а размер файла - около 2 МБ. В моем приложении 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 ответ
Макет виджета списка занимает слишком много времени. Установите список виджетов
uniformItemSizes
свойство к истине. Это позволяет избежать дорогостоящих операций макета. Другим способом было бы установитьlayoutMode
собственность наQListView::Batched
, Это позволяет избежать дорогой выкладки всех предметов одновременно.Не используйте
QListWidget
если нижние накладные расходыQListView
сделал бы.Добавления большого количества элементов должны быть пакетными, то есть не вставляйте элементы в модель один за другим. Вставка элементов из каждого пакета в элементарной операции, которая испускает
rowsInserted
или жеcolumnsInserted
сигнал только один раз.Вы не должны загружать файлы в потоке графического интерфейса. Это является источником плохого пользовательского опыта во многих приложениях, и его следует избегать с кучей презрения. Не делай этого.
Ниже приведен минимальный пример, который учитывает все это.
// https://github.com/KubaO/stackrun/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"