Russian Qt Forum
Ноябрь 27, 2024, 13:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Виртуальный QListView  (Прочитано 24962 раз)
IUnknown
Гость
« : Май 06, 2005, 13:52 »

Как реализовать виртуальный список для обработки огромного количества данных?
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #1 : Май 06, 2005, 14:51 »

поподробнее что значит обработка
что значит огромного?
Записан
ANM
Гость
« Ответ #2 : Май 06, 2005, 15:47 »

QListView отображает некий набор данных, обычно копия отображаемых данных хранится в самом QListView. Но если объем данных очень большой то держать копию данных в QListView нерационально. В LISTVIEW из Common Controls для этого есть режим виртуального списка, при работе в котором данные не хранятся в ListView, а сам ListView делает запрос к внешнему источнику данных когда эти данные ему нужно отобразить.
Это должно быть по идее, как же без этого...
Записан
IUnknown
Гость
« Ответ #3 : Май 06, 2005, 18:04 »

Конечно должно быть! Только мне интересно как этого добится?! В винде все понятно LVS_OWNERDATA да LVN_GETDISPINFO и виртуальность готова. Помогите если кто знает, а то уж слишком долго грузится список. Заранее благодарен.
Записан
IUnknown
Гость
« Ответ #4 : Май 06, 2005, 22:36 »

Копнул англоязычные ресурсы и понял что стандартного способа НЕТ (может плохо копал), а реализовать виртуальность нужно самому с самого начала. Есть какой-то бедненький пример с QTable, но с него толку мало. Вывод - мелкософт РУЛИТ!!
Записан
Ruslan Popov
Гость
« Ответ #5 : Май 07, 2005, 09:21 »

Твой вопрос подробно описан в одном из ежеквартальников Qt. Есть специальные обработчики у QListView, вешаешь на них подкачку данных в QListView и всё работает. Только не говори, что в WinAPI - это автоматически делается Улыбающийся

updated
поискал, не нашел... но где-то видел готовый пример...

updated
Нашел! Тебе надо посмотреть в сторону QScrollView:
The contentsMoving() signal is emitted just before the contents are moved to a new position.
В обработчике этого сигнала, надо реализовать замену данных в QListView, будет всё быстро!
Записан
ANM
Гость
« Ответ #6 : Май 07, 2005, 14:58 »

Код:
void QScrollView::contentsMoving ( int x, int y ) [signal] 
This signal is emitted just before the contents are moved to position (x, y).

Это слишком низкоуровневое событие. LISTVIEW из commctl вызывает callback когда ему нужны данные для изображения элемента списка.
В параметрах callback он передает номер элемента списка по которому он запрашивает данные.
Возможно QTable реализует подобную функциональность.
Цитировать
Large tables
For large, sparse, tables using QTableItems or other widgets is inefficient. The solution is to draw the cell as it should appear and to create and destroy cell editors on demand.
This approach requires that you reimplement various functions. Reimplement paintCell() to display your data, and createEditor() and setCellContentFromEditor() to support in-place editing. It is very important to reimplement resizeData() to have no functionality, to prevent QTable from attempting to create a huge array. You will also need to reimplement item(), setItem(), takeItem(), clearCell(), and insertWidget(), cellWidget() and clearCellWidget(). In almost every circumstance (for sorting, removing and inserting columns and rows, etc.), you also need to reimplement swapRows(), swapCells() and swapColumns(), including header handling.
If you represent active cells with a dictionary of QTableItems and QWidgets, i.e. only store references to cells that are actually used, many of the functions can be implemented with a single line of code. (See the table/bigtable/main.cpp example.)
For more information on cells see the QTableItem documenation.

Правда заставляют самостоятельно рисовать элементы. И перехватить нужно кучу сигналов.
Записан
IUnknown
Гость
« Ответ #7 : Май 07, 2005, 23:40 »

А примера готового нету?
Записан
ANM
Гость
« Ответ #8 : Май 11, 2005, 10:21 »

Пример есть в qt - C:\Qt\3.3.4\examples\table\bigtable.
Код:

const int numRows = 1000000;
const int numCols = 1000000;

class MyTable : public QTable
{
public:
    MyTable( int r, int c ) : QTable( r, c ) {
items.setAutoDelete( TRUE );
widgets.setAutoDelete( TRUE );
setCaption( tr( "A 1 Million x 1 Million Cell Table" ) );
setLeftMargin( fontMetrics().width( "W999999W" ) );
    }

    void resizeData( int ) {}
    QTableItem *item( int r, int c ) const { return items.find( indexOf( r, c ) ); }
    void setItem( int r, int c, QTableItem *i ) { items.replace( indexOf( r, c ), i ); }
    void clearCell( int r, int c ) { items.remove( indexOf( r, c ) ); }
    void takeItem( QTableItem *item )
    {
items.setAutoDelete( FALSE );
items.remove( indexOf( item->row(), item->col() ) );
items.setAutoDelete( TRUE );
    }
    void insertWidget( int r, int c, QWidget *w ) { widgets.replace( indexOf( r, c ), w );  }
    QWidget *cellWidget( int r, int c ) const { return widgets.find( indexOf( r, c ) ); }
    void clearCellWidget( int r, int c )
    {
QWidget *w = widgets.take( indexOf( r, c ) );
if ( w )
   w->deleteLater();
    }

private:
    QIntDict<QTableItem> items;
    QIntDict<QWidget> widgets;

};

Насколько я понял, в этом примере оптимизация для разряженной таблицы, т.е. реально хранятся только те ячейки значения для которых были введены.
Лично мне нужна виртуальность в смысле редактирования и отображения данных в таблице. QT это позволяет делать, ну а если QT хочет хранить на каждую ячейку наследника от QTableItem и от QWidget то меня это устраивает.
Если виртуальность нужна для действительно больших таблиц то наверное лучше воспользоваться QDataTable и QDataView.
Записан
Kostya.
Гость
« Ответ #9 : Май 11, 2005, 11:37 »

Я наверно чего-то не так понял, но можно и не хранить копию данных в ListView. Достаточно отнаследоваться от QListViewItem и переопределить функцию text(), в результате имеем тоже что и если бы вызывались GETDISPINFO и т.д.

P.S. Кстати медленное заполнение ListView может быть связано с тем что данные в список добавляются не в конец, а в начало. И поэтому он постоянно перерисовывается.
Записан
ANM
Гость
« Ответ #10 : Май 11, 2005, 12:04 »

Не все так просто при таком подходе Веселый Текст действительно в QListViewItem хранится не будет. Но объекты QListViewItem будут созданы для каждого элемента в QListView. Допустим кол-во строк в таблице 100 000, следовательно как минимум столько же объектов QListViewItem будет создано. LISTVIEW (commctl) может не хранить никакой информации об отображаемых элементах, он запоминает только общее кол-во элементов в таблице для того чтобы правильно рисовать скроллбар.
Записан
Kostya.
Гость
« Ответ #11 : Май 11, 2005, 12:35 »

Цитата: "ANM"
Не все так просто при таком подходе Веселый Текст действительно в QListViewItem хранится не будет. Но объекты QListViewItem будут созданы для каждого элемента в QListView. Допустим кол-во строк в таблице 100 000, следовательно как минимум столько же объектов QListViewItem будет создано. LISTVIEW (commctl) может не хранить никакой информации об отображаемых элементах, он запоминает только общее кол-во элементов в таблице для того чтобы правильно рисовать скроллбар.


Постойте, но ведь при LVN_GETDISPINFO в параметре NMHDR*
хранится некая информация (LVITEM), т.е. Значит это не просто количество элементов, а некое описание каждого элемента, т.е. грубо говоря тот же QListViewItem.

Чем плохо что будет создано 100 000 QListViewItem?
Записан
ANM
Гость
« Ответ #12 : Май 11, 2005, 13:09 »

Наоборот, эту структуру должен заполнить пользователь LISTVIEW Улыбающийся.
Цитировать

Parameters
Address of an NMLVDISPINFO structure. On input, the LVITEM structure contained in this structure specifies the type of information required and identifies the item or subitem of interest. Use the LVITEM structure to return the requested information to the control.


Ну и подробнее о LISTVIEW:

Цитировать
A virtual list view is a list-view control that has the LVS_OWNERDATA style. This style enables the control to handle millions of items because the owner receives the burden of managing item data. This allows you to use the virtual list-view control with large databases of information, where specific methods of data access are already in place.

A virtual list-view control maintains very little item information itself. Except for the item selection and focus information, the owner of the control must manage all item information. Other processes request item information from the owner by using LVN_GETDISPINFO notification messages.


Полного аналога в QT этому контролу по видимому нет.
Можно использовать QDataTable QDataView но они завязаны на БД.
А если ты лог захошешь выводишь в файл и заодно отображать его в своей программе и кол-во записей в логе может быть ~1000000, то QListView наверное не поможет.
Записан
Kostya.
Гость
« Ответ #13 : Май 11, 2005, 13:42 »

Цитата: "ANM"
Наоборот, эту структуру должен заполнить пользователь LISTVIEW Улыбающийся.


Правильно, но не всю.
Цитата: "ANM"

Цитировать

Parameters
Address of an NMLVDISPINFO structure. On input, the LVITEM structure contained in this structure specifies the type of information required and identifies the item or subitem of interest. Use the LVITEM structure to return the requested information to the control.


Значит всетаки не просто количество записей, присутствует еще и описание записи.
Цитата: "ANM"

Ну и подробнее о LISTVIEW:

Цитировать
A virtual list view is a list-view control that has the LVS_OWNERDATA style. This style enables the control to handle millions of items because the owner receives the burden of managing item data. This allows you to use the virtual list-view control with large databases of information, where specific methods of data access are already in place.

A virtual list-view control maintains very little item information itself. Except for the item selection and focus information, the owner of the control must manage all item information. Other processes request item information from the owner by using LVN_GETDISPINFO notification messages.


Полного аналога в QT этому контролу по видимому нет.
Можно использовать QDataTable QDataView но они завязаны на БД.
А если ты лог захошешь выводишь в файл и заодно отображать его в своей программе и кол-во записей в логе может быть ~1000000, то QListView наверное не поможет.


Только вот я не могу понять почему QListViewItem не может или не выполняет функцию LVITEM? Там же тоже храниться минимум описания записи. Всю остальную информацию ты можешь выдавать ему сам.
Почему вы считаете что LVITEM != QListViewItem?
Записан
ANM
Гость
« Ответ #14 : Май 11, 2005, 16:33 »

Потому что sizeof(QListViewItem) = 44, слишком дорого для одной записи. А LISTVIEW на самом деле не хранит никакой информации записях. Объясню почему:
Цитировать
virtual list-view control maintains very little item information itself. Except for the item selection and focus information, the owner of the control must manage all item information.

Размер информации о фокусе это sizeof(int), только одна запись имеет фокус. Информация о выбранных пользователем записях имеет динамический изменяющийся размер,и если нет выбранных записей то и размер равен 0. Как это сделано? Очень просто - связанный список например.
Итог: QListView обязательно расходует 44 байта на каждую запись, LISTVIEW может вообще расходовать 0 байт на запись если одновременно разрешено выбирать только одну запись.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.096 секунд. Запросов: 23.