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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Не работает двойная буферизация для QPainter  (Прочитано 6573 раз)
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://qt.osdn.org.ua/flicker-free.html
 - и я не понимаю их код, что такое за переменная lines-  она нигде не объявляется
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Ноябрь 02, 2012, 17:29 »

Буферизация в Qt работает без проблем.
Похоже дело в другом.
Показывай рабочий пример.
Записан

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

Сообщений: 2063


Просмотр профиля
« Ответ #2 : Ноябрь 02, 2012, 20:30 »

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

Это код для Qt3, там двойной буферизации не было, в Qt4 она есть.
Записан
Bepec
Гость
« Ответ #3 : Ноябрь 02, 2012, 21:23 »

Накось возьмись разберись похвались Улыбающийся

Записан
yarick
Гость
« Ответ #4 : Ноябрь 03, 2012, 12:29 »

Накось возьмись разберись похвались Улыбающийся

Спасибо большое за код, но смысл как раз в том, что линию "ломает" как раз когда под ней другие виджеты (например кнопки), и мы там мышкой проводим. Сейчас скину пример
Записан
yarick
Гость
« Ответ #5 : Ноябрь 03, 2012, 12:41 »

Выдрал из своего проекта данную проблему в маленький проект

Принцип следующий  - я конструирую оверлей для рисования поверх всех виджетов, как сказано здесь 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();
}
Записан
yarick
Гость
« Ответ #6 : Ноябрь 27, 2012, 12:42 »

Есть какие-нибудь идеи? А то ломанные линии раздражают
Записан
yarick
Гость
« Ответ #7 : Ноябрь 27, 2012, 17:45 »

Хотя я сам уже разобрался
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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