Russian Qt Forum

Qt => Model-View (MV) => Тема начата: EyeOnNet от Август 10, 2011, 12:54



Название: QListView и модель на основе QAbstractListModel - как правильно?
Отправлено: EyeOnNet от Август 10, 2011, 12:54
До недавнего времени успешно обходился классом QListWidget для отображения списков (из базы данных). Но вот появилась задача отобразить список с большим (от нескольких десятков тысяч до миллионов строк). Решил попробовать QListView. Сделал простую модель на основе класса QAbstractListModel - переопределил функции "rowCount()" и "data()", пробую, работает, только гораздо медленней, чем на QListWidget! Анализ показал, что список грузит из модели все строчки, а так как каждая из них формируется моделью из результата отдельного запроса к удаленной БД, неудивительно, что быстродействие оказалось плачевным. Но главное, это противоречит моему понимаю работы схемы модель/представление - я предполагал, что из модели никогда не будет грузиться намного больше, чем представление может одновременно отобразить на экране. Тем не менее, список грузит  подряд все строки, количество которых ему выдает rowCount(), и только загрузив последнюю, наконец-то отображает содержимое. После этого он уже работает примерно как положено, загружая в небольшом количестве строки только при листании списка. Рытье в google ответа не дало, возможно я упускаю какую-то мелочь и QListView должен и в момент инициализации работать как положено.

PS манипуляции с режимами вроде "setLayoutMode(QListView::Batched)" не помогли, в "Batched" режиме хотя приложение и не виснет до конца загрузки списка, но на экране он все равно пуст до окончания загрузки всех строк таблицы.


Название: Re: QListView и модель на основе QAbstractListModel - как правильно?
Отправлено: Пантер от Август 10, 2011, 13:09
Это неверное поведение. Сортировку устанавливал? Какие-нибудь настройки QListView менял?


Название: Re: QListView и модель на основе QAbstractListModel - как правильно?
Отправлено: Kolobok от Август 10, 2011, 13:09
и долго миллион запросов выполняется?
setUniformItemSizes ( bool enable ) поможет.


Название: Re: QListView и модель на основе QAbstractListModel - как правильно?
Отправлено: EyeOnNet от Август 10, 2011, 13:39
Это неверное поведение. Сортировку устанавливал? Какие-нибудь настройки QListView менял?

Думал что может действительно что-то нахимичил, создал новый QListView, результат такой же. Сортировку не ставил, кроме изменений layoutMode и batchSize остальные параметры оставались по-умолчанию.


Название: Re: QListView и модель на основе QAbstractListModel - как правильно?
Отправлено: EyeOnNet от Август 10, 2011, 13:48
и долго миллион запросов выполняется?
setUniformItemSizes ( bool enable ) поможет.
Терпения не хватило! Думаю очень долго. Снимал задачу на нескольких сотнях.  :D

Хм. После выполнения setUniformItemSizes(true); поведение изменилось - теперь QListView  выполняет только один запрос к модели, data(const QModelIndex &index, Qt::DisplayRole), и все. Список в окне пуст, программа работает, хотя подвисает.
Похоже для анализа прийдется сделать новое пустое приложение и там гонять списки.  

Собственно вот практически весь исходник пробного приложения:
Код
C++ (Qt)
 
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   Listt = new QListView(this);
   connect(ui->pushButton,SIGNAL(pressed()),this,SLOT(PushAction()));
 
}
 
MainWindow::~MainWindow()
{
   delete Listt;
   delete ui;
}
 
void MainWindow::PushAction(){
 
   model = new Mmodel();
   model->L1=ui->label;model->L2=ui->label_2;
   Listt->resize(200,50);
   Listt->setLayoutMode(QListView::Batched);
   Listt->setModel(model);
 
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
#include "mmodel.h"
 
Mmodel::Mmodel(QObject *parent) :
   QAbstractListModel(parent)
{
}
/* ------------------------------------------------ */
int Mmodel::rowCount(const QModelIndex &parent) const
{
static int Ccounter=0;
   Ccounter++;if(L1!=NULL)L1->setText(tr("Count rows gives=[%1]").arg(Ccounter));  
return 1000000;
}
// ====================
QVariant Mmodel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
static int Ccounter=0;
 
    if (role == Qt::DisplayRole){
 
        Ccounter++;if(L2!=NULL)L2->setText(tr("Count data gives=[%1]").arg(Ccounter));
 
        return tr("N=%1").arg(index.row());
           }
    else
        if (role == Qt::UserRole){
 
            return "---";
        }
    else
        return QVariant();
}
 


QListView по-прежнему грузит через "data()" с Qt::DisplayRole столько строк, сколько возвращает функция "rowCount()". Может надо обработать ещё какую-то роль, кроме "DisplayRole"? Или утановить какой-то флаг у QListView???


Название: Re: QListView и модель на основе QAbstractListModel - как правильно?
Отправлено: EyeOnNet от Август 17, 2011, 09:11
Вот тестовый проект. Проще некуда, но что неправильно так и не нашёл, хотя уже десятый раз перечитал описание класса QListView. Приходится думать, что первичная загрузка всех строк модели это нормальный режим для объекта этого класса. Может попробовать QTableView, может этот класс работает как положено? А может проблема в том, что я наследую класс модели от "QAbstractListModel" ?  Может представление при работе с потомками этого класса так и должно загружать данные полностью?