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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Как рисовать на QImage  (Прочитано 14807 раз)
Alex_C
Гость
« : Апрель 11, 2012, 13:15 »

Эта тема - в продолжении моей темы
http://www.prog.org.ru/topic_21417_0.html
Собственно есть задача: отрисовка карты местности. На местности каждый объект представляет собой набор точек, которые нужно перевести из точек на местности, в точки на экране. Тут все без проблем. Проблема вот в чем:
если я создаю несколько десятков достаточно сложных QPolygon и затем на событие paintEvent отрисовываю их QPainter.drawPolygon - получается раз 5-10 медленнее, чем когда было на на Дельфи , при рисовании в памяти на Bitmap, а затем отрисовка целикового битмапа куда надо.
Почитав форум, понял что так делать не верно. Рекомендуется отрисовывать все на QImage, и его уже QPainter.drawImage.
Однако вопрос - а как рисовать полигоны, линии и т.п. на QImage - там есть только действия с отдельными точками?
Надеюсь понятно объяснил задачу. Улыбающийся
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Апрель 11, 2012, 13:33 »

См. базовый класс у QImage.
См. конструктор у QPainter.
Выводы должен сделать сам)
Записан

Qt 5.11/4.8.7 (X11/Win)
Alex_C
Гость
« Ответ #2 : Апрель 11, 2012, 15:02 »

См. базовый класс у QImage.
См. конструктор у QPainter.
Выводы должен сделать сам)

Спасибо! Навело на мысли Улыбающийся
Хотел бы уточнить вот что: правильно ли я понимаю: QPainter - это то, что в Дельфи называется Canvas? Т.е. получая объект канвас(в Qt пайнтер) рисуем на нем - хоть в памяти в QImage , хоть прямо на виджете?

В таком случае получается правильное решение - создавать QPainter от QImage, рисовать на нем (фактически рисуем то на QImage), и затем выводим этот QImage уже на QPainter нужного нам виджета?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Апрель 11, 2012, 15:37 »

В таком случае получается правильное решение - создавать QPainter от QImage, рисовать на нем (фактически рисуем то на QImage), и затем выводим этот QImage уже на QPainter нужного нам виджета?
Теоретически да. И вроде бы рисовать на QImage/QPixmap можно в др нитке (или неск нитками)
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Апрель 11, 2012, 16:10 »

И вроде бы рисовать на QImage/QPixmap можно в др нитке (или неск нитками)
на QPixmap навряд-ли, т.к. это ресурс XServer/GDI.
Записан

Qt 5.11/4.8.7 (X11/Win)
Alex_C
Гость
« Ответ #5 : Апрель 11, 2012, 16:35 »

Ок! Спасибо, понятно. Сделал. Появился такой вопрос:
Определил у себя в классе, отвечающим за рисование в конструкторе следующее
Код:
    m_Image = new QImage(m_iWidth, m_iHeight, QImage::Format_RGB32);
    m_Painter = new QPainter(m_Image);
далее в отдельной ф-ции создаю нужный рисунок, и определил ф-цию
Код:
void MapWindow::drawMap(QPainter &p)
{
    p.drawImage(QPoint(0, 0), *m_Image);
}
которая должна вызываться из события paint нужного мне виджета.
В результате у меня рисуется черный квадрат.
До этого когда рисовал на полученном указатете QPainter &p от ф-ции drawMap - все рисовалось нормально.
Чего то еще не учел?
Записан
Alex_C
Гость
« Ответ #6 : Апрель 11, 2012, 16:52 »

И что уж мне совсем не понятно - если такой кусок кода в ставить в конструктор

Код:
    m_Painter->setPen(QPen(Qt::lightGray,1,Qt::SolidLine));
    m_Painter->setBrush(Qt::blue);
    m_Painter->drawEllipse(QPoint(m_cX, m_cY), m_r, m_r);

То на drawMap(QPainter &p) нарисуется эллипс.
а если так

Код:
void MapWindow::drawMap(QPainter &p)
{
    m_Painter->setPen(QPen(Qt::lightGray,1,Qt::SolidLine));
    m_Painter->setBrush(Qt::blue);
    m_Painter->drawEllipse(QPoint(m_cX, m_cY), m_r, m_r);

    p.drawImage(QPoint(0, 0), *m_Image);
}

ничего... напомню, ф-ция drawMap вызывается на событие пайнт виджета, на котором рисую.
Почему так?
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #7 : Апрель 11, 2012, 17:02 »

Код:
void MapWindow::drawMap(QPainter &p)
Как создан p?
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Апрель 11, 2012, 17:07 »

Не делайте m_Painter членом класса, просто объявляйте как локальный перед каждым рисованием QImаge. Ну или вызывайте m_Painter->end() в конце каждого рисования
Записан
Alex_C
Гость
« Ответ #9 : Апрель 11, 2012, 22:03 »

Код:
void MapWindow::drawMap(QPainter &p)
Как создан p?


Эта ф-ция вызывается из пайт эвента виджета, на котором я хочу рисовать. Вот его реализация

Код:
void MapPaintWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    CalcWindow(this->parentWidget()).mapWindow->drawMap(p);
}

На такую "странную" конструкцию вызова через предка не обращайте внимание - это я разные способы вызова экспериментирую)))

Не делайте m_Painter членом класса, просто объявляйте как локальный перед каждым рисованием QImаge. Ну или вызывайте m_Painter->end() в конце каждого рисования

Очень интересное замечание! А почему так? Разве не быстрее 1 раз создать, чем каждый раз при перерисовке объекта? Или есть какие то подводные камни?
Записан
Alex_C
Гость
« Ответ #10 : Апрель 12, 2012, 08:38 »

В общем я тут немного не правильно написал.  Подмигивающий
Если делать так:

Код:
void MapWindow::drawMap(QPainter &p)
{
    QPainter p2(m_Image);
    p2.setPen(QPen(Qt::lightGray,1,Qt::SolidLine));
    p2.setBrush(Qt::blue);
    p2.drawEllipse(QPoint(m_cX, m_cY), m_r, m_r);

    p.drawImage(QPoint(0, 0), *m_Image);
}

все рисуется.

я вот если ф-ию drawMap разбить на 2 ф-ции

Код:
void MapWindow::createMap()
{
    QPainter p2(m_Image);
    p2.setPen(QPen(Qt::lightGray,1,Qt::SolidLine));
    p2.setBrush(Qt::blue);
    p2.drawEllipse(QPoint(m_cX, m_cY), m_r, m_r);
}

void MapWindow::drawMap(QPainter &p)
{
    p.drawImage(QPoint(0, 0), *m_Image);
}


и потом пытаться вызывать из paintEvent

Код:
void MapPaintWidget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    CalcWindow(this->parentWidget()).mapWindow->createMap();
    CalcWindow(this->parentWidget()).mapWindow->drawMap(p);
}

То рисования не происходит.
Понятно что объект QPainter p2 будет только в ф-ции createMap. Но я считал, что он рисует на  m_Image. Или я все не не правильно понимаю объект QPainter?
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #11 : Апрель 12, 2012, 10:27 »

Или я все не не правильно понимаю объект QPainter?
Именно.
QPainter-у позволительно рисовать на виджете только в paintEvent() данного виджета.


И перед тем как городить огород всё-таки не мешало почитать описание по QPainter:
Цитата: assistant
Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent widget attribute is set. On Mac OS X and Windows, you can only paint in a paintEvent() function regardless of this attribute's setting.
« Последнее редактирование: Апрель 12, 2012, 10:29 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Alex_C
Гость
« Ответ #12 : Апрель 12, 2012, 10:40 »

Да это я знаю... Я просто действительно пытался огород городить ))) Сейчас все заработало.
Одно НО - все равно рисуется конечно существенно медленнее, чем это рисовалось у меня на Дельфи(((
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #13 : Апрель 12, 2012, 10:46 »

Одно НО - все равно рисуется конечно существенно медленнее, чем это рисовалось у меня на Дельфи(((
Как минимум одна причина известна изначально - в Qt встроенный double-buffering.
И сглаживание включено?
Записан

Qt 5.11/4.8.7 (X11/Win)
Alex_C
Гость
« Ответ #14 : Апрель 12, 2012, 17:21 »

Как минимум одна причина известна изначально - в Qt встроенный double-buffering.
И сглаживание включено?

Да вроде сейчас во всем разобрался - медленнее конечно, но не так уж сильно как казалось по началу))

Кстати setRenderHint особой разницы не заметил...

Спасибо за советы! Принимаю к сведению!))
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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