Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: yarick от Ноябрь 02, 2012, 16:59



Название: Не работает двойная буферизация для QPainter
Отправлено: yarick от Ноябрь 02, 2012, 16:59
В таймере перерисовываю виджет через repaint()

в paintEvent у меня код рисования

Код:
QPainter p(this);

p.setOpacity(.4);
p.setRenderHint(QPainter::Antialiasing);
p.setPen(QPen(Qt::blue,2,Qt::SolidLine));
p.drawLine(0,0,QCursor::pos().x(),QCursor::pos().y());
p.end();

Т.е. рисуется стрелочка из (0,0) экрана в позицию курсора. Если дёргать курсор в разные стороны - то возникает мерцание... хотя это даже не мерцание, стрелочку РВЁТ на куски, я заснял видео, по кадрам посмотрел и скрин приложу.

Здесь  http://doc.crossplatform.ru/qt/4.6.x/qt4-arthur.html#widget-double-buffering (http://doc.crossplatform.ru/qt/4.6.x/qt4-arthur.html#widget-double-buffering) заявлено, что двойная буферизация поддерживается виджетами

С другой стороны пытался сам её реализовать как сказано здесь http://qt.osdn.org.ua/flicker-free.html (http://qt.osdn.org.ua/flicker-free.html)
 - и я не понимаю их код, что такое за переменная lines-  она нигде не объявляется


Название: Re: Не работает двойная буферизация для QPainter
Отправлено: GreatSnake от Ноябрь 02, 2012, 17:29
Буферизация в Qt работает без проблем.
Похоже дело в другом.
Показывай рабочий пример.


Название: Re: Не работает двойная буферизация для QPainter
Отправлено: Alex Custov от Ноябрь 02, 2012, 20:30
С другой стороны пытался сам её реализовать как сказано здесь http://qt.osdn.org.ua/flicker-free.html (http://qt.osdn.org.ua/flicker-free.html)
 - и я не понимаю их код, что такое за переменная lines-  она нигде не объявляется

Это код для Qt3, там двойной буферизации не было, в Qt4 она есть.


Название: Re: Не работает двойная буферизация для QPainter
Отправлено: Bepec от Ноябрь 02, 2012, 21:23
Накось возьмись разберись похвались :)



Название: Re: Не работает двойная буферизация для QPainter
Отправлено: yarick от Ноябрь 03, 2012, 12:29
Накось возьмись разберись похвались :)

Спасибо большое за код, но смысл как раз в том, что линию "ломает" как раз когда под ней другие виджеты (например кнопки), и мы там мышкой проводим. Сейчас скину пример


Название: Re: Не работает двойная буферизация для QPainter
Отправлено: yarick от Ноябрь 03, 2012, 12:41
Выдрал из своего проекта данную проблему в маленький проект

Принцип следующий  - я конструирую оверлей для рисования поверх всех виджетов, как сказано здесь http://www.qtcentre.org/wiki/index.php?title=Widget_Overlay (http://www.qtcentre.org/wiki/index.php?title=Widget_Overlay)

Для оверлея я сделал отдельный класс-виджет TopTranspWid
Суть проблемы я уже понял - я делаю так
Код:
setAttribute(Qt::WA_TransparentForMouseEvents);
Отключается обработка движения мыши, не перерисовывается, и как следствие - куски стрелки остаются на прошлом месте. Если эту строчку кода убрать - то графических артефактов не будет, но кнопки под стрелокой будет не нажать.

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

Я сам представляю такие пути решения - а)рисовать без оверлея, каким-то другим путём б)перехватывать через фильтр события оверлея и перенаправлять на кнопки (пытался так сделать, но не работает)

Исходники и скрин приложу в виде файлов. И здесь тоже -

Класс оверлея
Код:
#ifndef TOPTRANSPWID_H
#define TOPTRANSPWID_H

#include <QWidget>

class TopTranspWid : public QWidget
{
  Q_OBJECT
public:
  explicit TopTranspWid(QWidget *parent = 0);
  void paintEvent(QPaintEvent *event);
public slots:
  void updateTimerSlot();
};

#endif // TOPTRANSPWID_H

Код:
#include "toptranspwid.h"
#include "QtGui"

TopTranspWid::TopTranspWid(QWidget *parent) :QWidget(parent)
{
  QTimer *timer = new QTimer(this);
  connect(timer, SIGNAL(timeout()), this, SLOT(updateTimerSlot()));
  timer->start(30);

  resize(parent->size());

  //Эта строчка - корень проблемы. Если её убрать, то клики не будут проходить сквозь виджет
  //Но с ней игнорируются также и события движения мыши - не наступает перерисовки и поверх других виджетов остаются куски рисунка
  setAttribute(Qt::WA_TransparentForMouseEvents);
}

void TopTranspWid::paintEvent(QPaintEvent* event)
{
  QPainter p(this);

  //Рисуем стрелочку из центра экрана в точку курсора, но на виджете. Не спрашивайте, почему
  p.setPen(QPen(Qt::blue,2,Qt::SolidLine));
  p.drawLine(0,0,QCursor::pos().x(),QCursor::pos().y());
  p.end();

  event->accept();
}

void TopTranspWid::updateTimerSlot()
{
  repaint();//Вызываем repaint

  //Кстати если вызвать parentWidget()->repaint() или даже parentWidget()->parentWidget()->repaint()
  //Это всё равно не поможет - полная перерисовка почему-то всё равно помогает
}

main.cpp
Код:
#include "testpaint.h"
#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
testPaint w;
w.show();
return a.exec();
}


Название: Re: Не работает двойная буферизация для QPainter
Отправлено: yarick от Ноябрь 27, 2012, 12:42
Есть какие-нибудь идеи? А то ломанные линии раздражают


Название: Re: Не работает двойная буферизация для QPainter
Отправлено: yarick от Ноябрь 27, 2012, 17:45
Хотя я сам уже разобрался