Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Nimbus от Декабрь 15, 2011, 07:05



Название: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 07:05
Передо мной стоит задача запихнуть в один виджет 700-900 почти одинаковых виджетов. Соответственно иду по самому простому пути:
1. Создаю QScrollArea *pArea
2. Создаю QWidget *pWidget, кладём в него QVBoxLayout *layout
3. В каком-то сферическом цикле в вакууме добавляем виджеты в *layout
4. pArea->setWidget(pWidget);
5. pArea->show();

Проблема вся в том, что между 4 и 5 действиями проходят нехилые 2 секунды. Это много. По моему скромному мнению, для pWidget вызывается рекурсивный вызов перерисовки всех дочерних виджетов. Как можно обойти данный изъян, перерисовывая, например, только видимые виджеты? Или, может, есть аналогичные QScrollArea виджеты для решения такой задачи?


Название: Re: QScrollArea со множеством виджетов
Отправлено: Bepec от Декабрь 15, 2011, 07:22
Прошу уточнить, а зачем? Что надо сделать?

Ибо ваша задача... неоптимальна скажем так.

PS проверял, что 1к виджетов типа "QPushButton" тормозят двухъядерную машину :)


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 07:37
Возможно, да. Нужно каким-то способом отображать в один момент времени, например, 10 из 1000 виджетов. И прокручивать скроллбаром этот родительский виджет. Это всё сводится к созданию виджета с 10-ю позициями для дочерних виджетов и скроллбаром. По мере прокрутки уничтожать виджеты и на их месте создавать новые. Но тут возникает ещё две проблемы:
  • все виджеты разного размера и могут менять свой размер в процессе работы, поэтому полосу для прокрутки и размер ползунка не высчитать сразу;
  • виджеты изменяются сами по себе в процессе работы (может текст в каком-то поменяется, может цвет, может добавятся новые в него виджеты), поэтому сохранять их состояние тоже весьма проблематично


Название: Re: QScrollArea со множеством виджетов
Отправлено: Fat-Zer от Декабрь 15, 2011, 08:09
может тогда глянуть в сторону Model/View? Вроде это всё должно из коробки появиться при реализации своего вида [FIXME]...


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 08:20
может тогда глянуть в сторону Model/View? Вроде это всё должно из коробки появиться при реализации своего вида [FIXME]...
А вы уверены, что какой-нибудь QListView работает именно так как я хочу, и нет провисания между установкой модели и отображением?

P. S. посмотрел сейчас событие paintEvent у pWidget - оно всё-таки вызывается позже этого провисания. Выходит, дело не в перерисовке.


Название: Re: QScrollArea со множеством виджетов
Отправлено: Bepec от Декабрь 15, 2011, 08:25
Уважаемый JC.

Приведу простой пример:
5,000 QPushButton созданный как виджеты - загрузка 2 ядер на 100%, тормоза при прокручивании/перерисовки.

10,000,000 QPushButton, отрисовываемых в делегате модели (model-view) - никаких тормозов :)

Желаю вам посмотреть в сторону model-view.

PS модель работает быстрее, чем простой QScrollArea и тормозов нету.


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 08:29
Bepec, а можете опубликовать для меня исходники, пожалуйста?


Название: Re: QScrollArea со множеством виджетов
Отправлено: Bepec от Декабрь 15, 2011, 09:17
Природная жадность говорит нет. :) Т.к. разработка коммерческая.

Сейчас попробую пример наваять :) вот его могу скинуть.


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 10:40
Bepec, буду очень признателен


Название: Re: QScrollArea со множеством виджетов
Отправлено: Bepec от Декабрь 15, 2011, 10:42
Внутри чисто код, на 1 кк кнопочек. Конечно времени на разбирание и использование этого кода, уйдет намного больше, но эффект тоже будет немаленьким.


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 11:01
Спасибо!

Код
C++ (Qt)
QApplication::style()->drawControl(QStyle::CE_PushButton,&but, painter);
 
Только один вопрос: как быть с кастомными виджетами в этом случае?


Название: Re: QScrollArea со множеством виджетов
Отправлено: Bepec от Декабрь 15, 2011, 12:03
Ну вот тут вопрос встает -а что за виджеты и зачем тебе надо и какие :)

Опиши подробнее задачу ^^


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 12:08
Ну вот тут вопрос встает -а что за виджеты и зачем тебе надо и какие :)

Опиши подробнее задачу ^^

Скажем так кастом-виджет с CSS-стилем, в нём, например, 3 QLabel'а, причём, у двух из них установлены пиксмапы.


Название: Re: QScrollArea со множеством виджетов
Отправлено: GreatSnake от Декабрь 15, 2011, 12:11
Может имеет смысл перейти на QGraphicsView/Scene?


Название: Re: QScrollArea со множеством виджетов
Отправлено: Bepec от Декабрь 15, 2011, 12:14
скажем так - мне неясно зачем такое, что с ними можно делать (редактировать или нажимать их можно или нельзя), потому мб тебе стоит попробовать всё самому.

GreatSnake плохого не скажет :)


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 15, 2011, 12:23
скажем так - мне неясно зачем такое, что с ними можно делать (редактировать или нажимать их можно или нельзя), потому мб тебе стоит попробовать всё самому.

GreatSnake плохого не скажет :)
Да не важно, считай, что проблема не в этом. Как я понимаю, для редактирования достаточно реализовать метод QStyledItemDelegate::createEditor.
Главное, нарисовать в QPainter виджет. Может стоит посмотреть на какой-нибудь QPixmap::grabWidget?


Название: Re: QScrollArea со множеством виджетов
Отправлено: BRE от Декабрь 15, 2011, 12:36
Главное, нарисовать в QPainter виджет. Может стоит посмотреть на какой-нибудь QPixmap::grabWidget?
Вообще есть
void QWidget::render ( QPaintDevice * target, const QPoint & targetOffset = QPoint(), const QRegion & sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags( DrawWindowBackground | DrawChildren ) )
который все нарисует.


Название: Re: QScrollArea со множеством виджетов
Отправлено: Командор от Декабрь 15, 2011, 16:02
Передо мной стоит задача запихнуть в один виджет 700-900 почти одинаковых виджетов. Соответственно иду по самому простому пути:
1. Создаю QScrollArea *pArea
2. Создаю QWidget *pWidget, кладём в него QVBoxLayout *layout
3. В каком-то сферическом цикле в вакууме добавляем виджеты в *layout
4. pArea->setWidget(pWidget);
5. pArea->show();

Проблема вся в том, что между 4 и 5 действиями проходят нехилые 2 секунды. Это много. По моему скромному мнению, для pWidget вызывается рекурсивный вызов перерисовки всех дочерних виджетов. Как можно обойти данный изъян, перерисовывая, например, только видимые виджеты? Или, может, есть аналогичные QScrollArea виджеты для решения такой задачи?

А без layout как со скоростью? Просто делал что-то похожее, но без layout, рисуя виджеты на pWidget. При этом, конечно, нужно вручную контролировать место рисования виджетов на pWidget. При количестве виджетов порядка 10000 загрузка процессора при прокрутке была 5-7%. Тогда как модели давали 15% загрузки. Что касается времени отображения, то оно практически нулевое, т.к. перерисовываются только отображаемые виджеты.


Название: Re: QScrollArea со множеством виджетов
Отправлено: Nimbus от Декабрь 20, 2011, 05:33
Всё-таки остановился на Qt Quick и ихнем Model-View. Гораздо проще реализовать и всё более красиво выглядит