简体   繁体   English

QGraphicsView和eventFilter

[英]QGraphicsView and eventFilter

This has been bugging me for more than two days now, so i thought i should ask. 这已经困扰了我两天多了,所以我想我应该问。 I am using Qt 4.5.3 (compiled with VC2008) on Win7. 我在Win7上使用Qt 4.5.3(用VC2008编译)。

I have MyGraphicsView (inherits QGraphicsView) and MyFilter (inherits QObject) classes. 我有MyGraphicsView(继承QGraphicsView)和MyFilter(继承QObject)类。

When i install the MyFilter object as an event filter to MyGraphicsView, Mouse events are delivered to MyFilter after they are delivered to MyGraphicsView whereas Key events are delivered to MyFilter before they are delivered to MyGraphicsView. 当我将MyFilter对象作为事件过滤器安装到MyGraphicsView时,鼠标事件在传递到MyGraphicsView 传递给MyFilter,而Key事件在传递给MyGraphicsView 之前传递给MyFilter。

In the second case, i install the MyFilter object as an event filter to MyGraphicsView->viewport() (which is a standart QGLWidget), Mouse events are delivered to MyFilter before they are delivered to MyGraphicsView, whereas Key events are delivered to only MyGraphicsView. 在第二种情况下,我安装MyFilter对象作为事件过滤器MyGraphicsView->视口()(其是非标准QGLWidget来绘图),鼠标事件被传递到MyFilter它们被输送到 MyGraphicsView,而关键事件被传递到 MyGraphicsView 。

The events are supposed to be delivered to event filters before they are delivered to the actual object, so why is this happening? 事件应该在传递给实际对象之前传递给事件过滤器,为什么会发生这种情况呢? What should i do to ensure this order? 我该怎么做才能确保这个订单?

Thanks in advance. 提前致谢。 Best Regards. 最好的祝福。

QGraphicsView is a subclass of QAbstractScrollArea which is the cause of these behaviors. QGraphicsView是QAbstractScrollArea的子类,它是这些行为的原因。

In the first case, the QAbstractScrollArea adds itself as a event filter to the MyGraphicsView when setViewport() is called. 在第一种情况下,当调用setViewport()时,QAbstractScrollArea将自身添加为MyGraphicsView的事件过滤器。 The QAbstractScrollArea's event filter captures the mouse event, first sends it through viewportEvent(), and then to the QWidget event handling which propagates to the MyGraphicsView mouse event handlers. QAbstractScrollArea的事件过滤器捕获鼠标事件,首先通过viewportEvent()发送它,然后传递给传播到MyGraphicsView鼠标事件处理程序的QWidget事件处理。 Only after this is the QAbstractScrollArea's event filter finished and MyFilter gets to run. 只有在这之后,QAbstractScrollArea的事件过滤器才会完成并且MyFilter才能运行。

In the second case, key events are delivered only to the MyGraphicsView because in setViewport() the QAbstractScrollArea sets itself as the focus proxy. 在第二种情况下,关键事件仅传递给MyGraphicsView,因为在setViewport()中,QAbstractScrollArea将自身设置为焦点代理。 If the focus proxy is reset with the following code, the key events will be delivered. 如果使用以下代码重置焦点代理,则将传递键事件。

w.viewport()->setFocusProxy(0);

An alternative is to install the event filter on both the graphics view and its viewport, but modify the filter to only process key events from one object and mouse events from the other. 另一种方法是在图形视图及其视口上安装事件过滤器,但修改过滤器以仅处理来自一个对象的键事件和来自另一个对象的鼠标事件。

Change MyFilter.h 改变MyFilter.h

  QObject *keyObj;
  QObject *mouseObj;

public:
  MyFilter(QObject *keyObj, QObject *mouseObj, QObject *parent = NULL);

Change MyFilter.cpp 更改MyFilter.cpp

MyFilter::MyFilter(QObject *keyObj, QObject *mouseObj, QObject *parent /*= NULL*/ ) : QObject(parent), keyObj(keyObj), mouseObj(mouseObj)

and

if (obj == keyObj && e->type() == QEvent::KeyPress)
{
    qDebug()<<"Key Event recieved by MyFilter";
}
else if (obj == mouseObj && e->type() == QEvent::MouseButtonPress)
{
    qDebug()<<"Mouse Event recieved by MyFilter";
}

Change main.cpp 改变main.cpp

MyFilter *filter = new MyFilter(&w, w.viewport(), &w);

// Use this line to install to the viewport
w.viewport()->installEventFilter(filter);

//Use this line to install to MyGraphicsView
w.installEventFilter(filter);

How about to try not using filter but reimplement necessary QEvent handlers at MyGraphicsView like here: 如何尝试不使用过滤器,但在MyGraphicsView重新实现必要的QEvent处理程序,如下所示:

void MyGraphicsView::mousePressEvent(QMouseEvent* pe)
{
if (pe->buttons() & Qt::LeftButton)
{
    this->setCursor(Qt::CrossCursor);
    zoomOrigin = pe->pos();
    rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
    rubberBand->setGeometry(QRect(zoomOrigin, QSize(0,0)));
    rubberBand->show();
}
if (pe->buttons() & Qt::MidButton)
{
    panOrigin = pe->pos();
        this->setCursor(Qt::ClosedHandCursor);
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM