PDA

View Full Version : How to pass events from QWidget covering QMainWindow?



SeeLook
28th January 2013, 22:11
I have QGraphicsView that covers main window (its size and QGraphicsScene size are the same as the window).
I'm useing it to display animated hints.
I made it transparent for mouse events by

setAttribute(Qt::WA_TransparentForMouseEvents, false);

I would like to make those hints clikable so I need to change thet attribute,
but then main window is covered from mouse events.
I tried to reimplement QGraphicsView::event


bool MyGraphicsView::event(QEvent* event) {
m_parent->event(event);
return QGraphicsView::event(event);
}

m_parent is QMainWindow


bool MainWindow::event(QEvent *event) {
return QMainWindow::event(event);
}


but it crash on:

return QMainWindow::event(event);

Yes, I can adjust QGraphicsView to some hints and cover only needed part of the window
but it is much of work.
Maybe Is there any trick?

lanz
29th January 2013, 08:23
QWidget::event () function is protected for a reason, you shouldn't make it public.
You experiencing crash because you are propagating ALL the events (and it's ChildAdded event that messes up internal mechanics and crashes the app).

To achieve desired functionality you should reimplement only mouseEvent () and use post/sendEvent to propagate mouse events to the MainWindow.

SeeLook
29th January 2013, 11:50
Thans for reply.

It doesn't work.
I debuged MainWindow::event(), it gots MouseButtonPress event there but it isn't propagated to appropirate Buttons over those was clicked.

Also i tried opposite:
I made QGraphicsView transparent for mose events and I sended MainWindow events to it.
Also QGraphicsView::event() handler sees the events but QGraphicsTextItem doesn't send linkActivated(QString) signal after click.
In this case (MainWindow sends events to QGraphicsView)
all what I need it to get this signal working.
I have
setTextInteractionFlags(Qt::TextBrowserInteraction );
and this works when
setAttribute(Qt::WA_TransparentForMouseEvents) is set to false

So what do You think about it?

wysota
29th January 2013, 14:37
Don't make anything transparent to anything. Your problem is that you are trying to handle events in an incorrect place. For handling events that happen in graphics view (e.g. for graphics item), handle them in Graphics View architecture (i.e. in the scene. the view or in items themselves). If you want to handle events that happen outside the graphics view, handle them in a widget containing the view or in the view itself. If an event is ignored, it will propagate to the parent thus if you have a graphics view over some other widget and you makre sure the event is ignored, it will pass through to the parent widget. See QEvent::ignore().

Another thing is whether doing animated hints by covering your main widget with graphics view is that good of an idea. It seems much simpler to make a hint a custom widget, possibly one that makes use of Qt::ToolTip.

SeeLook
31st January 2013, 16:01
I reimplemented QGraphicsScene
methods:
mousePressEvent(QGraphicsSceneMouseEvent* event) and
mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
I had got for each method:

myScene::mousePressEvent(QGraphicsSceneMouseEvent* event) {
event->ignore();
QGraphicsScene::mousePressEvent(event);
}
then events started occur in QGraphicsView
(That one wich covering the MainWindow)
I did the same in QGraphicsView reimplementation
but events heven't occured in MainWindow
When I call

myQGraphicsView::mousePressEvent(QMouseEvent *event) {
event->ignore();
qApp->sendEvent(parent, event);
}


MainWindow invokes mousePressEvent()
but widgets in MainWindow can't get it even i put event->ignore() inside

Any ideas?

P.S.
I found in the web a few similar threads but none solved

SeeLook
31st January 2013, 21:53
I found a reason (I think) why MainWindow doesn't propagate that events.
It seems, events are moving "up to the hill" from children to parent
QGraphicsScene->QGraphicsView->MainWindow
but MainWindow can't send that event to other children back.

Also I tried opposite
I'm handling mousePress and mouseRelease events in
QMainWindow::event() reimplementation


if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
myQGraphicsView->event(event);
}

in QGraphicsView the events are nicely propageted to its scene
and reimpemented method
QGraphicsTextItem::event()
shows those events
But i don't know why QGraphicsTextItem doesn't emit linkActiveted signal
(I'm sure all is redy for this, I mean
item->setTextInteractionFlags(Qt::TextBrowserInteraction );
)

SeeLook
4th February 2013, 19:10
I made this working.
Let's assembly how.

I have MainWindow (QMainWindow covered by QGraphicsView

MainWindow have many widgets and View is used to show some tips and descriptions, sometimes animated.
To keep MainWindow responsible on mouse events I must add

myGraphicsView->setAttribute(Qt::WA_TransparentForMouseEvents)

but I needed QGraphicsTextItem placed in the View to be clickable and able to sending linkActivated(QString linkAddress)

I obtained this by:
1. Handling events in MainWindow and redirect some to myGraphicsView
(QGraphicsView::event() is protected so classes have to be friends or event() reimplementation has to be public)


bool MainWindow::event(QEvent *event) {
if (event->type() == QEvent::MousePressEvent || event->type() == QEvent::MouseReleaseEvent) {
myGraphicsView->event(event);
}
return QMainWindow::event(event);
}


2. Invokeing mouse related methods in QGraphicsView::event() reimplementation



myGraphicsView::event(QEvent *event) {
if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *me = static_cast<QMouseEvent *>(event);
me->setAccepted(false);
if (event->type() == QEvent::MouseButtonPress)
QGraphicsView::mousePressEvent(me);
else
QGraphicsView::mouseReleaseEvent(me);
}
return QGraphicsView::event(event);

}


Event are redirected to QGraphicsScene there and all is working as expected.
Reimplementation of QGraphicsTextItem nicely emits linkActivated signal.

For me it was enought to redirect exacly that two events but for some others porposes You maybe need more.

Thanks for all clues.