LINUX.ORG.RU

Переход от QScrollArea к QGraphicsView

 ,


0

1

Всем привет. Есть приложение, которое отображает большое кол-во (>1000) наследников QFrame. Для их отображения я выбрал QScrollArea, вот код

QFrame *substrate = new QFrame();
substrate -> setObjectName("visitorListSubstrate");
areaFrameLay = new QVBoxLayout(substrate);
areaFrameLay -> setMargin(0);
areaFrameLay -> setSpacing(1);
areaFrameLay -> addStretch();

area = new MyScrollArea();
area -> setObjectName("VisitorListArea");
area -> setWidget(substrate);
area -> setWidgetResizable(true);
area -> setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
area -> verticalScrollBar() -> setObjectName("chatsScrollBar");

...
for(auto item : items) {
    ...
    areaFrameLay -> insertWidget(index, item);
}
Пока ячеек было ~100, все было норм, но вот когда нагрузка возросла, то все стало тормозить. В итоге я начал профайлить приложение, сделал пару оптимизаций. Все стало как бы ок, но вот при добавлении 1000 ячеек, содержимое QScrollArea как бы прыгает... Стал гуглить и нагуглил, что лучше использовать QGraphicsView и QGraphicsScene, т.к. они перерисовывают только видимую часть... Пытался сделать переход на них, но у меня не получилось, точнее, после этого дергания пропали, все стало красиво и быстро, но получил две проблемы:

  • CSS не применяются к элементам внутри сцены (пришлось явно вызывать setStyleSheet для объектов). parent указать не смог объектам сцены, наткнулся на runtime ошибку
  • Ячейки приняли статический размер и не растягиваются вместе с самим QGraphicsView (а мне это нужно..)

Вот код, который я пробовал

scene = new QGraphicsScene(this);
area = new QGraphicsView(scene, this);

QFrame *substrate = new QFrame();
substrate -> setObjectName("visitorListSubstrate");
areaFrameLay = new QVBoxLayout(substrate);
areaFrameLay -> setMargin(0);
areaFrameLay -> setSpacing(1);
areaFrameLay -> addStretch();

scene -> addWidget(substrate)
Вот скрины, чтобы было понятно о чем речь было и стало Подскажите, что я делаю не так

Ответ на: комментарий от grondek

Разраб до меня писал на MVC, уперся в производительность... Я ощущал на себе, что MVC нельзя использовать при большом кол-ве представлений...

energyclab ()
Ответ на: комментарий от energyclab

Ну ладно, мое мнение по производительности другое, но фиг с ним.

Ячейки приняли статический размер и не растягиваются вместе с самим QGraphicsView (а мне это нужно..)

При растягивании QGraphicsView ты не растягиваешь саму сцену. Тебе надо, например, в QGraphicsView::resizeEvent сделать ресайз сцены до нужного размера.

parent указать не смог объектам сцены, наткнулся на runtime ошибку

Там вроде обязательно QWidget::parent должен быть == 0. Поэтому родителя и нет.

grondek ()
Ответ на: комментарий от energyclab

Я ощущал на себе, что MVC нельзя использовать при большом кол-ве представлений...

QListView весьма быстрый, но если нужна максимальная производительность — стоит посмотреть в сторону QTableView, он тысячу элементов должен легко прожевать, так что я бы предложил для начала написать какой-нибудь минимальный прототип, чтобы проверить на своих задачах.

CrossFire ★★★★★ ()
Ответ на: комментарий от grondek

При растягивании QGraphicsView ты не растягиваешь саму сцену. Тебе надо, например, в QGraphicsView::resizeEvent сделать ресайз сцены до нужного размера

Пробовал, сцена растягивается, содержимое - нет.

Там вроде обязательно QWidget::parent должен быть == 0. Поэтому родителя и нет.

Да, это я уже понял, иначе рендерить одельно не получится...

В итоге я решил все просто через resizeEvent

void VisitorList::resizeEvent(QResizeEvent *e) {
    QFrame::resizeEvent(e);
    substrate -> resize(area -> width(), substrate -> height());
}

energyclab ()
Ответ на: комментарий от energyclab

А по поводу производительности: у нас один из QTableView отображает порядка 10000*20 ячеек модели, а вообще в приложении 50-70 вьюх на 20 моделей с проксями. В моделях в среднем по 3-5 тысяч строк. И долго происходит только начальная загрузка, потом все летает.

grondek ()

Кхм, интересные скриншоты. Видно, что никакого нативного виндового гуя тут нет. Хочется сказать что-то вроде:«Будь мужиком, напиши свой виджет, который отображает только то, что умещается на экране и не создает в памяти дополнительные списки данных, хранящих дублированную информацию, которые ещё надо как-то синхронизировать». Но это сложно.

С использованием QListView+«делегат»+«своя модель» так же будут трудности, если нужна интерактивносить отдельных сущностей внутри кастомного элемента списка. Надо будет перехватывать мышь или решать проблему как-то по другому.

Можно не извращаться, отказаться от своего чудо-дизайна и отображать все обычными гуевыми списками, таблицами, деревьями.

В итоге, ИМХО, по какому бы пути не пошел, в любом случае надо чем-то пожертвовать. Выбирай.

pathfinder ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.