Выдрал из своего проекта данную проблему в маленький проект
Принцип следующий - я конструирую оверлей для рисования поверх всех виджетов, как сказано здесь
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();
}