首页 > 解决方案 > 如何在自定义 Qt 类上安装事件过滤器?

问题描述

我想在 Qt 中的自定义类的对象上安装事件过滤器。所以我在QtGuiApplication1Qt Designer 上创建了一个项目,并创建了一个简单的类,myClass它有一个小部件和一个用于绘制彩色矩形的 QGraphicsView。

在头文件中:

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
#include "myClass.h"

class QtGuiApplication1 : public QMainWindow
{
    Q_OBJECT
public:
    QtGuiApplication1(QWidget *parent = Q_NULLPTR);
private:
    Ui::QtGuiApplication1Class ui;
    bool eventFilter(QObject *obj, QEvent *ev);
    myClass* myClass_;
};

在.cpp

#include "QtGuiApplication1.h"


QtGuiApplication1::QtGuiApplication1(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    myClass_ = new myClass(this, QRect(100, 100, 200, 200));
    myClass_->installEventFilter(this);
}

bool QtGuiApplication1::eventFilter(QObject * obj, QEvent * ev)
{

    if (obj == myClass_)
    {
        bool hi = true;
    }

    return false;
}

myClass 代码在这里:

myClass的头文件:

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QObject>
#include <QGraphicsView>

class myClass : public QObject
{
    Q_OBJECT
public:
    explicit myClass(QObject *parent = 0);
    myClass();
    myClass(QWidget* parent, QRect inRect);
private:
    QWidget * widget;
    QGraphicsView* qGraph_back;
    QGraphicsScene* scene_back;

};

#endif /

myClass的cpp文件:

#include "myClass.h"

myClass::myClass(QObject *parent) :
    QObject(parent)
{
}

myClass::myClass()
{
}
myClass::myClass(QWidget* parent, QRect inRect)
{
    widget = new QWidget(parent);
    qGraph_back = new QGraphicsView(widget);
    scene_back = new QGraphicsScene(qGraph_back);

    widget->setGeometry(inRect);
    scene_back->setSceneRect(0,0,inRect.width(),inRect.height());
    qGraph_back->setBackgroundBrush(QColor(0, 0, 255, 80));
    qGraph_back->setScene(scene_back);
    qGraph_back->show();
}

我想获取myClass_对象的所有事件,例如鼠标事件,但我不能,并且事件过滤器不起作用。如何在对象上安装 eventfilter?

标签: qtclasseventfilter

解决方案


事件过滤器仅适用于您的MyClass实例中的事件。不是为了它的孩子。

因此,您的方法中的事件(例如鼠标单击或移动)qGraph_back将不可见eventFilter

当您在小部件中添加子项时,QChildEvent会引发一个事件。您可以使用它在所有孩子(和孙子等)上安装事件过滤器。MyClass但是,在添加孩子之前,您必须在您的设备上安装事件过滤器。

一个简单的例子:

class Listener: public QObject
{
public:
        Listener(): QObject()
        {}

        bool eventFilter(QObject* object, QEvent* event)
        {
            qDebug() << Q_FUNC_INFO << object << event;
            if (event->type() == QEvent::ChildAdded)
            {
                QChildEvent* ev = dynamic_cast<QChildEvent*>(event);
                ev->child()->installEventFilter(this);
            }
            return false;
        }
};

class Widget: public QWidget
{
    public:
Widget(QObject* parent) : QWidget()
{
    installEventFilter(parent);
    QGraphicsView* view = new QGraphicsView(this);
    auto layout = new QHBoxLayout(this);
    layout->addWidget(view);
    layout->addWidget(new QLabel("Foobar"))
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Listener* listener = new Listener();
    Widget* w = new Widget(listener);
    w->show();
    return app.exec();
}

如您所见,QLabel现在将发送到侦听器中的事件。但是,您无法从视图中看到事件,因为它们被...中的视口小部件捕获。QGraphicsView

您必须处理添加的孩子有视口(继承自QAbstractItemView等)并且它变得更加复杂的情况。

因此,如果您必须知道用户何时点击您的视图,则使用信号/槽而不是事件过滤器会更容易。


推荐阅读