Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: ilyagoo от Август 28, 2008, 09:14



Название: Рисование на QImage, эффект мерцания
Отправлено: ilyagoo от Август 28, 2008, 09:14
Доброго времени суток.
Вопрос следующий: пишу свой виджет для отрисовки графиков и т.д., что-то похожее на QwtPlot (этот компонент сильно грузит проц, а загрузка нужна минимальная). Рисую в буфере QImage в массиве bits(), потом вываливаю это на экран painter.drawImage(). QImage закрашиваю синим, точки ставлю желтым (впрочем это не важно, просто для примера, нужно рисовать разными цветами). Пока работаю по таймеру startTimer(100). Каждый раз добавляю линию точек снизу виджета, предварительно сдвинув картинку на линию же вверх. Эдакий "водопад падающий вверх".
Несмотря на буферизацию, экран мерцает жутко, в QwtPlot мерцания нет! Как мне избавится от этого эффекта?
Если нужен код - выложу. Юзаю (Qt-4.2.2 + VS2005 в WinXP) && (Qt-4.2.2 + gcc 4.с копейками в Linux)


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: Alex03 от Сентябрь 01, 2008, 05:58
setAutoFillBackground (false); ?


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: ilyagoo от Сентябрь 01, 2008, 14:52
ни false ни true эффекта не оказывают :(


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: Tonal от Сентябрь 02, 2008, 07:51
Если я правильно помню, Qt применяет буферизацию для рисования виджетов.
Если ты делаешь её сам, то дефолтную надо отрубить. :)


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: Alex03 от Сентябрь 02, 2008, 10:20
Ну тогда минимальный код с проблемой в студию...


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: ilyagoo от Сентябрь 02, 2008, 11:49
Код:
// 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();
}


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: Alex03 от Сентябрь 02, 2008, 15:27
так нет никакого мерцания.
Это по всей видимости поведение LCD монитора на такой картинке.
У меня мерцание тоже наблюдаются, но если таскать всё окно со сдвигом на пиксел - эфект тот же.

Например попробуйте подцепить CRT монитор или изменить startTimer(100); на startTimer(10);


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: ilyagoo от Сентябрь 03, 2008, 09:39
На трубке действительно не мерцает, только работать будет на ЖК. Повторю: QwtPlot не мерцает нигде!!!
В реальном времени обновление будет происходить 30-40 раз в секунду, а на экране будет от одного до четырёх таких окон.
Возникает еще один вопрос: как все это сжимать/растягивать адекватно?


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: Alex03 от Сентябрь 03, 2008, 14:29
На трубке действительно не мерцает, только работать будет на ЖК. Повторю: QwtPlot не мерцает нигде!!!
В Qwt мерцает также, просто там Ваших картинок нет...
Посмотрите пример data_plot при таймауте 100.
А теперь попробуйте заменить в нём
Код:
    d_y[0] = sin(phase) * (-1.0 + 2.0 * double(rand()) / double(RAND_MAX));
на
Код:
    static int f=0; d_y[0] = f++ & 1 ? -1.0 : 1.0;
а потом ещё сделайте не красным по серому, а как у Вас желтым по синему...

ИМХО проблема в том что у LCD пикселы "тухнут" быстрее чем "загораются".
На реальной картинке всё будет лучше.


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: ilyagoo от Сентябрь 04, 2008, 13:45
Цитировать
а потом ещё сделайте не красным по серому, а как у Вас желтым по синему...

ИМХО проблема в том что у LCD пикселы "тухнут" быстрее чем "загораются".

А как же тогда игры? Там-то прорисовка побыстрее и ничего не мелькает, иначи LCD не имели бы будущего ???


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: ритт от Сентябрь 04, 2008, 14:16
а можно замерять сколько времени занимает отработка 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];
//...
это ж не смещение влево/вправо - можно и memcpy использовать...

а вообще, если в QwtPlot не мерцает, наверное имеет смысл ковырять код QwtPlot?


Название: Re: Рисование на QImage, эффект мерцания
Отправлено: Alex03 от Сентябрь 05, 2008, 05:50
А как же тогда игры? Там-то прорисовка побыстрее и ничего не мелькает, иначи LCD не имели бы будущего ???
1. В играх нет таких сверхконтрастных картинок как в Вашем исходном примере. Попробуйте рисовать желтые точки не в 1-ом из 3-х случаев а в сотне, как мерцание? Уменьшилось?
2. В играх всё динамичнее, я уже предлагал Вам изменить в исходном примере таймаут с 100 на 10 мс.
3. Можно сгладить резкое загорание/потухание пиксела ценой производительность, например двигать картинку в 10 раз чаще на 1/10 пиксела с антиалиасингом.
4. Ну и не поленитесь Qwt пример изменить как я предлагал...