Qt - 传递事件到多个对象? [英] Qt -- pass events to multiple objects?

查看:417
本文介绍了Qt - 传递事件到多个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基本上有3层( Window> Scene> View ),每个都需要处理 mouseMove 事件而不阻塞其他。似乎只有最小的孩子正在得到的事件。我希望我可以处理事件,然后调用 event-> ignore()将事件传递回堆栈,但它似乎并不工作。



一些相关的代码,如果你需要它:

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

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

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

只打印C。请注意, EditorScene EditorView 接收不同类型的鼠标事件,因此不太容易传递它们。



EditorWindow 也需要鼠标坐标;目前我正在从一个孩子被发现一个信号被窗口抓住...但它不应该真的需要继续它的方式,应该吗?






找到此很好的文章。调用 ignore()告诉Qt找到另一个接收者。听起来应该可以工作,但也许这意味着一个不相关的接收器。传播它的正确方法实际上是调用 BaseClass :: Event 如下:

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

现在它正在打印BCBCBC ...这是伟大的,但我不能...






另一个编辑:It 正确传播,我只是没有启用 setMouseTracking

解决方案

  QGraphicsView :: mouseMoveEvent(event); 

不会传播到父级 - 它实际上传播到场景。 >

这是发生了什么 - QGraphicsView接收QMouseEvent,将其转换为QGraphicsSceneMouseEvent并将其传递到场景。场景然后将其传递到适当的项目,或在你的情况下,打印B。然后,如果你明确忽略事件(默认情况下鼠标移动被接受),Qt事件处理程序将通过该事件处理程序。事件到EditorView的父级。



另一件关于鼠标移动的事情是:


如果关闭鼠标跟踪,则只有在移动鼠标时按下鼠标按钮才会发生鼠标移动事件。如果鼠标跟踪已打开,即使没有按下鼠标按钮,也会发生鼠标移动事件。


因此,请确保您已启用跟踪EditorView的父级(或者你按下按钮:))。



编辑:
BTW,EditorScene不是EditorView的父级。嗯,这是在你的代码中,但只有在QObject的意义的父母(内存管理只)。



QGraphicsScene和View没有正常的家庭关系 - 场景可以有多个视图,这些视图是无关父节点的子项。



对于窗口事件传播,您必须具有基于QWidget的父节点。事实上,我很确定你的EditorView对EditorWindow或其中的一个孩子(当你将它添加到布局中)时,你会拒绝。



INSTAEDIT:
坐标您希望查看自己发出的信号。这两个解耦的原因,因为你可能想显示视图的本地坐标,而不是父窗口,而不是屏幕坐标(右?)。如果你真的想要场景坐标,View是正确的选择,因为它知道转换矩阵。



坐标像这样:
屏幕 - > EditorWindow local - EditorView local - >场景转换 - >任何本地转换的项目。


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.

解决方案

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.

这篇关于Qt - 传递事件到多个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆