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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Рисование на QImage, эффект мерцания  (Прочитано 10619 раз)
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)
Записан
Alex03
Гость
« Ответ #1 : Сентябрь 01, 2008, 05:58 »

setAutoFillBackground (false); ?
Записан
ilyagoo
Гость
« Ответ #2 : Сентябрь 01, 2008, 14:52 »

ни false ни true эффекта не оказывают Грустный
Записан
Tonal
Гость
« Ответ #3 : Сентябрь 02, 2008, 07:51 »

Если я правильно помню, Qt применяет буферизацию для рисования виджетов.
Если ты делаешь её сам, то дефолтную надо отрубить. Улыбающийся
Записан
Alex03
Гость
« Ответ #4 : Сентябрь 02, 2008, 10:20 »

Ну тогда минимальный код с проблемой в студию...
Записан
ilyagoo
Гость
« Ответ #5 : Сентябрь 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();
}
Записан
Alex03
Гость
« Ответ #6 : Сентябрь 02, 2008, 15:27 »

так нет никакого мерцания.
Это по всей видимости поведение LCD монитора на такой картинке.
У меня мерцание тоже наблюдаются, но если таскать всё окно со сдвигом на пиксел - эфект тот же.

Например попробуйте подцепить CRT монитор или изменить startTimer(100); на startTimer(10);
« Последнее редактирование: Сентябрь 02, 2008, 15:31 от Alex03 » Записан
ilyagoo
Гость
« Ответ #7 : Сентябрь 03, 2008, 09:39 »

На трубке действительно не мерцает, только работать будет на ЖК. Повторю: QwtPlot не мерцает нигде!!!
В реальном времени обновление будет происходить 30-40 раз в секунду, а на экране будет от одного до четырёх таких окон.
Возникает еще один вопрос: как все это сжимать/растягивать адекватно?
Записан
Alex03
Гость
« Ответ #8 : Сентябрь 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 пикселы "тухнут" быстрее чем "загораются".
На реальной картинке всё будет лучше.
Записан
ilyagoo
Гость
« Ответ #9 : Сентябрь 04, 2008, 13:45 »

Цитировать
а потом ещё сделайте не красным по серому, а как у Вас желтым по синему...

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

А как же тогда игры? Там-то прорисовка побыстрее и ничего не мелькает, иначи LCD не имели бы будущего Непонимающий
Записан
ритт
Гость
« Ответ #10 : Сентябрь 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?
Записан
Alex03
Гость
« Ответ #11 : Сентябрь 05, 2008, 05:50 »

А как же тогда игры? Там-то прорисовка побыстрее и ничего не мелькает, иначи LCD не имели бы будущего Непонимающий
1. В играх нет таких сверхконтрастных картинок как в Вашем исходном примере. Попробуйте рисовать желтые точки не в 1-ом из 3-х случаев а в сотне, как мерцание? Уменьшилось?
2. В играх всё динамичнее, я уже предлагал Вам изменить в исходном примере таймаут с 100 на 10 мс.
3. Можно сгладить резкое загорание/потухание пиксела ценой производительность, например двигать картинку в 10 раз чаще на 1/10 пиксела с антиалиасингом.
4. Ну и не поленитесь Qwt пример изменить как я предлагал...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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