LINUX.ORG.RU

Qt-4.4.1 и paintEvent, графика


0

0

Задача:

Написать виджет, который бы отрисовывал большое количество точек.

Желательно:

1) минимальная загрузка процессора PIII и выше, 2) отсутствие эффекта мерцания, 3) установка цвета каждой точки, 4) точки перемещаются по картинке "водопадом", т.е. каждый промежуток времени предыдущая картинка сдвигается на одну линию и добавляется линия с новыми точками, 5) масштабирование "без дыр", т.е. если увеличить/уменьшить картинку или растянуть/сжать виждет между точками не появлялось бы расстояний. Например, если это кривая с заливкой под ней, она бы растягивалась в ширину, а дыр в заливке не появлялось. В QwtPlotCurve из библиотеки Qwt 5.сколько-то со стилем отображения Sticks при растяжении графика появляются незакрашенные вертикальные полосы. К тому же QwtPlot загружает проц. 6) и т.д.

Решение:

Прорисовку осуществляю в массиве ipps32u (библиотеки Intel IPP). Копирую это дело в QImage по указателю bits(), вывожу на виджет с помощью QPainter. (только сейчас подумал, а не рисовать ли сразу в QImage::bits()?). При большом количестве цветов появляется эффект мерцания, но этого наверно не избежать=(

Но вот проблема: если ухватить мышью заголовок окна или развернуть его во весь экран (и наоборот), отрисовка на какое-то время замирает. Добавил в paintEvent виджета вывод в QStatusBar инкрементируемую внутри этого события переменную - она в это время не изменяется!!! Т.е. не приходит событие перерисовки!!! Причем, если время таймера поставить 10 мсек (пока рисую по timerEvent, но планируется рисование в реальном времени!) и держать мыщью заголовок окна, то событие отрисовки вообще не приходит=(( Есть ли какой-нибудь способ от этого избавиться? Qt необходимо, т.к. приложение д.б. кросс-платформенным, и API использовать нельзя.

>>Копирую это дело в QImage по указателю bits(), вывожу на виджет с помощью QPainter.

рисовать надо в QPixmap и QPainter'ом выводить уже этот pixmap. На виджет можно также поставить атрибут Qt::WA_OpaquePaintEvent

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

ну да, а что, имеет смысл компилить в линухе? не, нужно конечно, но изменится ли картина...

ilyagoo
() автор топика
Ответ на: комментарий от alex_custov

>>винда?

да, откомпилил, действительно этот эффект исчез.

вопрос вдогонку: тупо делаю окно из QmainWindow, например. Начинаю его дёргать, и тут, ни с того ни с сего исчезает курсор мыши (кстати, исправляюсь: не мыщью, а мышью)). Появляется только после рестарта X-сервера. В чем может быть проблема?

ilyagoo
() автор топика
Ответ на: комментарий от alex_custov

>>рисовать надо в QPixmap и QPainter'ом выводить уже этот pixmap.

из "Макс Шлее Qt4" (приблизительно):

"QImage - контекстно-независимое рисование. QPixmap - контекстно-зависимое рисование." Логичнее, наверное, было использовать QPixmap, но у него не получить доступ к буферу (я не нашел как), а в памяти рисовать быстрее, чем изпользовать функцию отрисовки каждой точки своим цветом. Хотя QPainter::drawImage сначала преобразует QImage в QPixmap. Короче, я так понимаю, что груже проц, а с QPixmap грузится видяха.

Библиотеки Intel выкинул, рисую сразу в QImage::bits().

Есть еще какие-то идеи?

Хотелось бы использовать видеокарту с помощью QPixmap, но как в нем добраться до буфера?

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

ну рисуй в QImage, потом преобразуй в QPixmap, и в paintEvent() выводи этот pixmap.

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

>>Так это точки или векторная графика? Причем здесь "кривые с заливкой"?

Графика растровая. QPixmap может рисовать кривые, а в Qwt их можно еще и "псевдозалить", т.е. под/над каждой точкой кривой автоматически проводится линия, вот и получается...

А есть идеи как рисовать векторно? OpenGL не предлагать=)

ilyagoo
() автор топика

Продолжение темы:

Размер виджета 480x360. Пока масштабирование не делал. Сравнение по загрузке проца: QwtPlot ~очень большая)), порядка 60-70%, моя отрисовка - 0-5%. Но! Мерцание экрана удручает((( В Qwt его нет, как мне избавиться от него? Использование Qt::WA_OpaquePaintEvent не помогает, и, по-моему, этот флаг стоит по умолчанию. К сожалению я пока не порос до того, чтобы разобрать Qwt от начала до конца, к тому же эта либа потянет за собой добрую часть Qt... Посоветуйте, пожалуйста, как устранить мерцание?

ilyagoo
() автор топика
Ответ на: комментарий от alex_custov

Код, поменьше...

// gimage.h

class GImage : public QImage

{

public:

GImage(int width = 640, int height = 480, Format format = QImage::Format_ARGB32_Premultiplied);

~GImage();

void drawGImage();

};

// gimage.cpp

void GImage::drawGImage()

{

uchar *ch = bits();

// передвигаю картинку вверх на строку

for (int i = 0; i < height()-1; ++i)

for (int j = 0; j < width(); ++j)

((int*)ch)[i * width() + j] = ((int*)ch)[(i+1)*width()+j];

// добавляю новую строку

for (int i = 0; i < width(); ++i)

if (qrand()%3 != 0)

((int*)ch)[(height()-1) * width() + i] = (int) qRgb(0,0,255);

else

((int*)ch)[(height()-1) * width() + i] = (int) qRgb(255,255,0);

}

// gplotter.h

class GPlotter : public QWidget

{

public:

GPlotter(QWidget *parent = 0);

~GPlotter();

protected:

void paintEvent(QPaintEvent *event);

void timerEvent(QTimerEvent *event);

private:

GImage im; // собственно буфер для отрисовки

};

// gplotter.cpp

GPlotter::GPlotter(QWidget *parent)

: Widget(parent)

{

setFixedSize(im.width(), im.height());

startTimer(100);

setAutoFillBackground(true); // эти строчки

setAttribute(Qt::WA_OpaquePaintEvent,true); // не спасают ((

}

void GPlotter::paintEvent(QPaintEvent *event)

{

QPainter painter(this);

painter.drawImage(0,0,im);

i++;

}

void GPlotter::timerEvent(QTimerEvent *event)

{

im.drawGImage();

update();

}

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

у меня ничего не мигает. Qt 4.3.3. И autoFillBackground нужно устанавливать в false, а не в true. Хотя в данном примере его можно вообще убрать.

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

>>у меня ничего не мигает. Qt 4.3.3

странно, надо будет попробовать понизить версию Qt. Кстати, мигает и в Windows и в Linux. В четверг продолжим обсуждение, если проблема не решится

ilyagoo
() автор топика
Ответ на: комментарий от alex_custov

Похоже придется попробовать 4.3.3, т.к. с версией 4.2.2 ничего не изменилось. Какое железо и дрова?

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