tags:

views:

890

answers:

2

I basically have 3 layers (Window > Scene > View) that each need to handle a mouseMove event without blocking the others. It seems only the youngest child is getting the event though. I was hoping I could process the event and then call event->ignore() to pass the event back up the stack, but it doesn't seem to be working.

Some relevant code if you need it:

void EditorWindow::createScene() {
 m_scene = new EditorScene(this);
 m_view = new EditorView(m_scene);
 // ...
}

void EditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
 printf("B\n");
 // ...
}

void EditorView::mouseMoveEvent(QMouseEvent* event) {
 printf("C\n");
 event->ignore();
}

Only "C" is being printed. Note that EditorScene and EditorView receive different types of mouse events so it's not completely trivial to pass them around.

The EditorWindow also needs the mouse coordinates; currently I'm sending a signal from one of the children which is caught by the window... but it shouldn't really be necessary to relay it that way, should it?


Found this nice article. Calling ignore() tells Qt to find another receiver. Sounds like it should work, but perhaps it means an unrelated receiver. The proper way to propagate it is actually to call BaseClass::Event like so:

void EditorView::mouseMoveEvent(QMouseEvent* event) {
    QGraphicsView::mouseMoveEvent(event); // propogate to parent widget
    printf("C\n");   
}

Now it's printing BCBCBC... which is great, but I can't seem to nudge it up one more level...


Another edit: It was being propogated up properly, I just didn't have setMouseTracking enabled.

+3  A: 
QGraphicsView::mouseMoveEvent(event);

Doesn't propagate up to the parent -- it actually propagates down to the scene.

Here is what's happens -- QGraphicsView receives QMouseEvent, translates it into QGraphicsSceneMouseEvent and passes it to the scene. Scene then passes it to appropriate item or, in your case, prints "B". Event handler then returns back to EditorView and prints "C".

Then, if you explicitly ignore event (mouse move is accepted by default), Qt event handler will pass the event to parent of EditorView. So try ignoring after you print "C".

Another thing about mouse move is this:

If mouse tracking is switched off, mouse move events only occur if a mouse button is pressed while the mouse is being moved. If mouse tracking is switched on, mouse move events occur even if no mouse button is pressed.

So make sure you have tracking enabled on parent of EditorView (or that you press buttons :)).

EDIT: BTW, EditorScene is not a parent of EditorView. Well, it is in your code, but only in QObject meaning of parentship (memory management only).

QGraphicsScene and View don't have normal family relationship -- scene can have multiple views and those views are children of unrelated parents.

For window event propagation purposes you must have QWidget based parent. In fact, I'm pretty sure you reparent EditorView to EditorWindow, or one of its children (when you add it into layout).

INSTAEDIT: For coordinates you want View itself to emit a signal. Both for decoupling reasons and because you probably want to show local coordinates of the view, and not of the parent window and not screen coordinates (right?). If you actually want scene coordinates, View is right choice too, because it knows transformation matrix.

Coordinates go like this: Screen -> EditorWindow local -> EditorView local -> Scene transformed -> whatever item local transformed.

Eugene
I think mouse tracking is switched on by default for QGraphicsScene.EditorScene is the parent of EditorView. I have no problem passing the event from EditorView to EditorScene with that last bit of code; it's getting it one level higher to EditorWindow that's the problem... although not a pressing issue at the moment.
Mark
Exactly. Does EditorWindow have mouse tracking enabled?
Eugene
Oh shoot...you're right. QGraphicsView doesn't need setMouseTracking but the main window does. It still won't pick up mouseMovement when hovering overtop of the other widgets though.
Mark
Basically I want the EditorWindow to grab the mouse coords when hovering overtop of the EditorView so that I can display the coords on the statusbar, which is a member of the EditorWindow. Would it better just for the scene to send a signal?
Mark
re: your edits: View knows the scene coords via `mapToScene` functions, but it doesn't have a `mouseMoveEvent` that gives them to you... I'm not quite convinced that sending the signal from the scene instead is a terrible idea, because even if you switch out the view for another one, it'll still make sense.
Mark
Yes, sending them from scene will work. But you wanted to send them from EditorWindow, no? :)
Eugene
Oh...well, I wasn't really considering that "sending" since the EditorWindow "owns" the StatusBar... but anyway, this way works and I think it makes proper modularity sense. Thank you for all your help!
Mark
+1  A: 

QGraphicsView::mousePressEvent( e ) in my mousePressEvent did the trick!