Russian Qt Forum

Qt => Вопросы новичков => Тема начата: NickSin от Март 03, 2014, 16:59



Название: Отрисовка большого числа объектов
Отправлено: NickSin от Март 03, 2014, 16:59
Суть проблемы такова.
Нужно создать сцены с отрисовкой большого количества квадратой , там их больше миллиона. Отрисовываются они сверху вниз.
Использую QGraphicScene  и QGraphicView.  Проблема в том, что если их отрисовываю больше 10 тысяч, программа виснет вся.

Хотелось бы узнать, в какую сторону мне стоит двигаться, чтобы решить проблему рисования такого числа объектов.

У меня пока что есть 2 варианта:
1) Динамическая подгрузка по мере пролистывания
2) использовать какой-то 2ой буффер для рисования.

Заранее спасибо.


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 03, 2014, 17:43
Виснет или вылетает или кончается память?


Название: Re: Отрисовка большого числа объектов
Отправлено: OKTA от Март 03, 2014, 19:03
знать бы еще что за квадраты и как рисуются подробнее  :)


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 10:42
Виснет или вылетает или кончается память?
Зависает, видимо идет за подкачкой, а это процесс медленные
знать бы еще что за квадраты и как рисуются подробнее  :)
Рисуются просто - по вертикали , сверху вниз. Квадрат обычный, только его отрисовка. Размер каждого из них 80х80.
Что-то вроде такого:
[]
[]
[]
[]
[]

ну и так 10000 штук.


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 05, 2014, 10:46
И тут вопрос уже конкретнее - память он всю выбирает (2Гб)?
Просто если вы делаете всё правильно, GraphicsView сама решает вопрос "скрытия" ненужных элементов.

PS мне кажется что у вас банально памяти не хватает :)


Название: Re: Отрисовка большого числа объектов
Отправлено: OKTA от Март 05, 2014, 10:58
Точняк что-то в алгоритме не то. Я тут ради интереса нарисовал 10000 квадратов 100x80 в QML и все ок - съело 50 мегабайт всего.
Хоть и QML, но он все равно использует все те же QGraphicScene и QGraphicView.
Поправьте if i'm wrong.


Название: Re: Отрисовка большого числа объектов
Отправлено: Old от Март 05, 2014, 11:20
Поправьте if i'm wrong.
У QML2 свой движек, не основанный на QGraphicsXXX.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 11:40
И тут вопрос уже конкретнее - память он всю выбирает (2Гб)?
Просто если вы делаете всё правильно, GraphicsView сама решает вопрос "скрытия" ненужных элементов.

PS мне кажется что у вас банально памяти не хватает :)
кушает 150 метров.
Тогда раз уж она такая умная, при скроле, жутко тормозит в половине обьектов, вторая половина обьектов скролится быстро!
Точняк что-то в алгоритме не то. Я тут ради интереса нарисовал 10000 квадратов 100x80 в QML и все ок - съело 50 мегабайт всего.
Хоть и QML, но он все равно использует все те же QGraphicScene и QGraphicView.
Поправьте if i'm wrong.
жаль я с ним не знаком как и с тем как он интегрируется в QT  приложение.
Поправьте if i'm wrong.
У QML2 свой движек, не основанный на QGraphicsXXX.
Об я точно не знал.

В общем суть в том, что когда начинаю 100000 или даже 1000000 он тупо не выводит и виснит.
на 100 тысячах сьедает около  1 гига, а вот на миллионе я подозреваю что ему захочется 10 гигов оперативы.
Вот я и думаю, может можно как то подгружать изображение по мере появления его в сцене, дабы убрать подвисания.
Или искать какую-то альтернативу, до которой я пока не додумался .


Название: Re: Отрисовка большого числа объектов
Отправлено: OKTA от Март 05, 2014, 11:49
Поправьте if i'm wrong.
У QML2 свой движек, не основанный на QGraphicsXXX.

Я про 1.1. Он, на сколько я знаю, как раз использует! Поправьте, если опять не прав))


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 11:50
Поправьте if i'm wrong.
У QML2 свой движек, не основанный на QGraphicsXXX.

Я про 1.1. Он, на сколько я знаю, как раз использует! Поправьте, если опять не прав))

забыл уточнить использую 5.2 qt


Название: Re: Отрисовка большого числа объектов
Отправлено: OKTA от Март 05, 2014, 11:51
Может пора код показать?


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 05, 2014, 12:03
10к объектов тем более однотипных для него не нагрузка. Если правильный код. Так что выкладывайте лучше всего проект минимально компилируемый, бум разбираться.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 12:12
Может пора код показать?
10к объектов тем более однотипных для него не нагрузка. Если правильный код. Так что выкладывайте лучше всего проект минимально компилируемый, бум разбираться.

ок для вывода создал диалог в нем QGraphicView
Код:
#include "../../headers/test_headers/dialog.h"
#include "ui_dialog.h"
#include <QtCore>
#include <QtGui>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

}

Dialog::~Dialog()
{
    delete ui;
}


void Dialog::paintEvent(QPaintEvent *)
{

    QGraphicsScene* scene;
    scene = new QGraphicsScene(this);
    scene->setBackgroundBrush( Qt::white );

    QPen pen( Qt::black );
    pen.setWidth( 1 );
    QBrush br( Qt::white );


    qreal w = 80.0;
    int numbers = 10000;

    for(int i = 0; i < numbers; i++){
        scene->addRect(QRectF(0.0, 100.0 + i*100, 80.0, 80.0),pen, br);
        if(i != numbers - 1)
            scene->addLine(QLineF(40.0, w + (i+1)*100, 40.0, w + (i+1)*100 + 20),pen);

        scene->addRect(QRectF(150.0, 100.0 + i*100, 80.0, 80.0),pen, br);
        if(i != numbers - 1)
            scene->addLine(QLineF(190.0, w + (i+1)*100, 190.0, w + (i+1)*100 + 20),pen);

        scene->addRect(QRectF(300.0, 100.0 + i*100, 80.0, 80.0),pen, br);
        if(i != numbers - 1)
            scene->addLine(QLineF(340.0, w + (i+1)*100, 340.0, w + (i+1)*100 + 20),pen);

        scene->addRect(QRectF(450.0, 100.0 + i*100, 80.0, 80.0),pen, br);
        if(i != numbers - 1)
            scene->addLine(QLineF(490.0, w + (i+1)*100, 490.0, w + (i+1)*100 + 20),pen);
    }



    ui->graphicsView->setScene(scene);


}

ну и тут пускаю 4 линии квадратов - получается 40 тысяч обьектов + линии связи между ними


Название: Re: Отрисовка большого числа объектов
Отправлено: Hellraiser от Март 05, 2014, 12:41
Код
C++ (Qt)
void Dialog::paintEvent(QPaintEvent *)
{
 
   QGraphicsScene* scene;
   scene = new QGraphicsScene(this);
без комментариев  :'(


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 12:50
Код
C++ (Qt)
void Dialog::paintEvent(QPaintEvent *)
{
 
   QGraphicsScene* scene;
   scene = new QGraphicsScene(this);
без комментариев  :'(
Я конечно понимаю, что все можно записать одной строкой или просто стат. обьект создать, но на тот момент когда я писал, я сильно не заморачивался )


Название: Re: Отрисовка большого числа объектов
Отправлено: Hellraiser от Март 05, 2014, 13:01
При чем здесь одна строка????? paintEvent может вызываться сотни, а то и тысячи раз в секунду. Если и дальше мысль непонятна, то может стоит начать с каких-нибудь книг, а не морочить людям голову?


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 05, 2014, 13:07
Начать стоит с главы "Рисование в Qt".
Там описывается алгоритм работы и зачем нужна функция paintEvent.

Вкратце - у вас при каждом перерисовке окна создаетcя QGraphicsScene.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 13:14
Начать стоит с главы "Рисование в Qt".
Там описывается алгоритм работы и зачем нужна функция paintEvent.

Вкратце - у вас при каждом перерисовке окна создаетcя QGraphicsScene.
вот блин, а на это я как-то внимания и не обратил, спасибо.
Про паинтевент уже прочел, косяк с памятью теперь понял.

Но все равно не могу понять как решить вопрос с более менее быстрой прокруткой созданных обьектов, ибо все равно первая часть из них при прокрутке тормозит, вторая часть -нет.


И если можно, то еще один вопрос. Я хочу на свои квадраты "нанести" текст.  Через методы класса rect, сцены  я это не увидел, точнее добавление текста есть в сцене, но не понял как задать позицию его размещения.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 13:24
При чем здесь одна строка????? paintEvent может вызываться сотни, а то и тысячи раз в секунду. Если и дальше мысль непонятна, то может стоит начать с каких-нибудь книг, а не морочить людям голову?
Извиняюсь за неточность своих суждений


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 05, 2014, 14:17
/offtop пишите update: и дальше своё сообщение. 2 сообщения подряд не комильфо.

А вы код приведите нормальный и именно с вашими тормозами.
Не тот, который не работает.
Не тот, который не запускается.
Не тот, который вы даже запускать не пробовали.
А тот, который вы запускали и который у вас тормозит и компилируется.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 05, 2014, 15:42
/offtop пишите update: и дальше своё сообщение. 2 сообщения подряд не комильфо.

А вы код приведите нормальный и именно с вашими тормозами.
Не тот, который не работает.
Не тот, который не запускается.
Не тот, который вы даже запускать не пробовали.
А тот, который вы запускали и который у вас тормозит и компилируется.
Спасибо за замечания, учту.

Код почти тот же, только убрал его из евента ( как было выяснено выше).
Сцена отрисовывется сразу в конструкторе диалога ( если что, прошу сильно не бить, хотел сделать для тестирования графики отдельное окно).
Обьекты на сцене всегда статичны и изменяться не будут.

Так вот я рисую  10000 обьектов  в памяти они занимают около 40 мб, запуск идет примерно секунды 3.  Проблема в том, что скролинг  первой половины квадратов идет с тормозами, а вторая прокручивается нормально.

Запуск кода с 100000 квадратами мне не удается ввиду того, что на машине, которой я пишу, памяти всего 2гб.
Update: код с 100000 квадратами запустился, но компилился 8 минут , в памяти занял 400 мб

П.С. и хотел бы узнать можно ли как то на квадраты добавить текст не наследую класс прямоугольника и не переопределяю методы. В просто добавлении текста в сцену, нельзя как я понял сменить ему координаты, ну или я просто не понял еще как это делается, так как Qt изучаю только 3тий месяц.

Сам код:
dialog.cpp
Код:
#include "../../headers/test_headers/dialog.h"
#include "ui_dialog.h"
#include <QtCore>
#include <QtGui>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    QGraphicsScene* scene = new QGraphicsScene(this);
    scene->setBackgroundBrush( Qt::white );

    QPen pen( Qt::black );
    pen.setWidth( 1 );
    QBrush br( Qt::white );


    qreal w = 80.0;
    int numbers = 100000;

    for(int i = 0; i < numbers; i++){
        scene->addRect(QRectF(0.0, 100.0 + i*100, 80.0, 80.0),pen, br);
        if(i != numbers - 1)
            scene->addLine(QLineF(40.0, w + (i+1)*100, 40.0, w + (i+1)*100 + 20),pen);

    }



    ui->graphicsView->setScene(scene);
}

Dialog::~Dialog()
{
    delete ui;
}

dialog.h
Код:
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QStyleOptionGraphicsItem>
#include <QPainter>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;

};

#endif // DIALOG_H

main.cpp
Код:
#include "../headers/test_headers/dialog.h"
#include <QApplication>



int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Dialog testgraph;
    testgraph.show();


    return app.exec();
}


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 05, 2014, 17:00
/offtop и выбрасывать проект не в виде
Код:
bla bla
а в виде архива с файлами и pro файлом внутри :P


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 07, 2014, 09:59
/offtop и выбрасывать проект не в виде
Код:
bla bla
а в виде архива с файлами и pro файлом внутри :P
Хорошо, я вас понял, спасибо за замечание.

Вот проект:http://sendfile.su/950202 (http://sendfile.su/950202)


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 07, 2014, 13:19
/offtop вы можете принять мои замечания за придирки, но это правила поведения на форуме ) Негласные ^.^

Посмотрел. На 10к не тормозит, на 20к не тормозит, на 40к не тормозит. Вот на 100к у меня начинается та же байда что и у вас - первая половина с тормозами, вторая нормально.

Но в любом случае стоит подумать, нужны ли вам эти миллионы квадратов. К тому же я так понимаю вы хотите в них ещё и текст засунуть, а потом ещё что нибудь прикрутить :P
PS цель у вас какая? Не то, чего вы хотите добиться сейчас, а что в конце вы хотите получить :P


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 07, 2014, 13:38
/offtop вы можете принять мои замечания за придирки, но это правила поведения на форуме ) Негласные ^.^
Да все норм)

Посмотрел. На 10к не тормозит, на 20к не тормозит, на 40к не тормозит. Вот на 100к у меня начинается та же байда что и у вас - первая половина с тормозами, вторая нормально.

Но в любом случае стоит подумать, нужны ли вам эти миллионы квадратов. К тому же я так понимаю вы хотите в них ещё и текст засунуть, а потом ещё что нибудь прикрутить :P
PS цель у вас какая? Не то, чего вы хотите добиться сейчас, а что в конце вы хотите получить :P
Я пытался экспериментировать с флагами ViewportUpdateMode и OptimizationFlags но успехов не добился. Где-то видел, что писали о наличии так называемого 2ного буфера для загрузки, но не знаю.... к месту он тут или нет?

Цель такова, что пишу графическое представление логов из файла. В файле может быть множество состояний, которые мне нужно вывести  в виде  таких квадратов( пока квадраты потом буду юзать полигон).
Правда пока не знаю как туда текст вбить, но хочу этого добиться.
Стараюсь рассмотреть все случаи отрисовки, точнее максимально возможный вариант,  чтобы потом  не мучится .


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 07, 2014, 14:04
Совет. Большой и доброжелательный - плюньте на вариант ""визуализация всего лога одновременно". Ничего кроме головной боли он вам не добавит :) Ибо 100 квадратов ~ 160Кб, 1к ~ 3,06 Мб, 1кк ~ 1,6 Гб, 2кк ~ 3,2 Гб. В логе может быть и больше :D ( примечание - квадратов без линий!!! )
Разбивайте по частям и уже их скармливайте во View. Размер части уже сами подбирайте в зависимости от количества событий (ну или строчек лога).

update: тем более если лог в текстовом формате, тогда и "леталку" по файлу надо делать. Было у меня одно время когда собирался подобное сделать, но другие дела похоронили проект :)


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 12, 2014, 10:05
Совет. Большой и доброжелательный - плюньте на вариант ""визуализация всего лога одновременно". Ничего кроме головной боли он вам не добавит :) Ибо 100 квадратов ~ 160Кб, 1к ~ 3,06 Мб, 1кк ~ 1,6 Гб, 2кк ~ 3,2 Гб. В логе может быть и больше :D ( примечание - квадратов без линий!!! )
Разбивайте по частям и уже их скармливайте во View. Размер части уже сами подбирайте в зависимости от количества событий (ну или строчек лога).

update: тем более если лог в текстовом формате, тогда и "леталку" по файлу надо делать. Было у меня одно время когда собирался подобное сделать, но другие дела похоронили проект :)
а можно по подробней как вы это реализовали или немного бы расписали идею, чтобы я уже делал в своем направлении) ?


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 12, 2014, 11:04
Ну смотрим. Допустим как у меня было - общение по оптоволокну с контроллером, который на себе держит много устройств. В секунду идёт примерно ммм... мб 10 информации :D строчек в логе в общем от 1 до 10к получается.
Примеряемся как хотим реализовать рисование -  я выбрал график состояний "--^-^-^". Поясняю - ровная линия всё ок, всплески - тревоги.
Отмеряем сколько нам нужно для "одновременного" показа на экране. У меня умешалось примерно 600 состояний.
Потом просто читаем первые 600, отдаём отрисовывать.
Пользователь тыкнул вниз - считываем ещё 1 (или к примеру ещё 600) от текущей позиции и отдаём на отрисовку.
scrollBar делаем свой, минимум - 0, максимум - содержимое файла лога / 600.
В принципе всё. Далее если пользун крутит scrollBar, просто читаем текущее положение скролла*600 из файла и отрисовываем.

Можно было конечно измудриться и сделать ещё кеширование +-600 для скорости, но мне скорости хватало.
Ещё дальше появился диапазон. Т.е. не разбиваем на части, а отдаём X записей = допустимая память / память занимаемая одной записью.

PS но дальше уже не развивалось, ибо я ушёл с того места работы.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 12, 2014, 11:20
Ну смотрим. Допустим как у меня было - общение по оптоволокну с контроллером, который на себе держит много устройств. В секунду идёт примерно ммм... мб 10 информации :D строчек в логе в общем от 1 до 10к получается.
Примеряемся как хотим реализовать рисование -  я выбрал график состояний "--^-^-^". Поясняю - ровная линия всё ок, всплески - тревоги.
Отмеряем сколько нам нужно для "одновременного" показа на экране. У меня умешалось примерно 600 состояний.
Потом просто читаем первые 600, отдаём отрисовывать.
Пользователь тыкнул вниз - считываем ещё 1 (или к примеру ещё 600) от текущей позиции и отдаём на отрисовку.
scrollBar делаем свой, минимум - 0, максимум - содержимое файла лога / 600.
В принципе всё. Далее если пользун крутит scrollBar, просто читаем текущее положение скролла*600 из файла и отрисовываем.

Можно было конечно измудриться и сделать ещё кеширование +-600 для скорости, но мне скорости хватало.
Ещё дальше появился диапазон. Т.е. не разбиваем на части, а отдаём X записей = допустимая память / память занимаемая одной записью.

PS но дальше уже не развивалось, ибо я ушёл с того места работы.

хм если честно просто и изящно выходит)  По сути, если задать значение сролл бару, а потом при скроллинге считывать строчки из файла, с позиции указанной нашим скроллом + то количество обьектов, которые мы видим на сцене = получает интервал строчек, которые мы считываем.
Тогда у меня вопрос,  перерисовка в таком случае быстро происходит?  Ибо как я понял, при перемещение скроллбара мы почти что покадрово "рисуем" лог из файла? 


Название: Re: Отрисовка большого числа объектов
Отправлено: Bepec от Март 12, 2014, 11:24
Отрисовка быстрая, но у меня не было никаких "раздутых" реализаций. Просто график.
По секрету скажу - все все view перерисовывают содержимое покадрово.

Подход простой, но не особо удобный - это была первая версия. Там нельзя подвинуть на  4-604, а можно было только 0-600 или 600-1200. Второй подход был удобнее для пользователей.

PS если заморочиться с перерисовкой, можно вообще типовые блоки сделать и их ляпать в виде pixmap. Кто-то писал что так оно ещё быстрее будет.


Название: Re: Отрисовка большого числа объектов
Отправлено: NickSin от Март 12, 2014, 11:36
Отрисовка быстрая, но у меня не было никаких "раздутых" реализаций. Просто график.
По секрету скажу - все все view перерисовывают содержимое покадрово.
Упустил этот момент спс)

Подход простой, но не особо удобный - это была первая версия. Там нельзя подвинуть на  4-604, а можно было только 0-600 или 600-1200. Второй подход был удобнее для пользователей.
Я немного не понимаю почему нельзя, по сути все норм должно быть.

PS если заморочиться с перерисовкой, можно вообще типовые блоки сделать и их ляпать в виде pixmap. Кто-то писал что так оно ещё быстрее будет.
Ну  про вывод сразу "готового" изображения я думал,  но мне нужно учесть еще возможность зуммирования обьектов,  а в pixmap я еще такого не делал, да  вообще не знаю, возможно ли оно, или нет