QT事件处理

一、QT事件管理

在Qt中主要由QApplication、QGUIApplication、QCoreApplication三个类来管理处理事件,具体的继承关系如下
在这里插入图片描述
QObject:所有Qt对象的基类。
QCoreApplication:主要用于提供无GUI程序的事件循环。
QGUIApplication:QGuiApplication类管理GUI应用程序的控制流和主要设置。它包含了主事件循环,所有来自窗口系统和其他源的事件都被处理和分派。它还处理应用程序的初始化和终结,并提供会话管理。
QApplication:QApplication专门为QGuiApplication提供了一些基于qwidget的应用程序所需的功能。
以上类在qt帮助文档中有讲述,可以查看帮助文档获取更多信息。

二、事件传递

Qt中的事件循环捕获各种事件,并将对应事件转化为带有事件信息的对象,然后由Qt的事件处理流程分发给需要处理事件的对象来处理事件。
在这里插入图片描述
其中exec()用于启动事件主循环,从事件队列中取出事件并创建一个对应的QEvent对象或其子对象来表示改事件;notify()函数对事件进行传递,最终由QObject::event()接收事件,event()负责将事件传递给目标对象并调用对应的事件处理函数。

传递规则如下:
若事件未被目标对象处理则不断向父类传递,如图所示
在这里插入图片描述
假设目标对象是四级窗口,信号在未被处理时会一直向父对象传递,直到被处理或者达到最顶层父对象为止。

三、事件处理

1、重写QWidget中接收事件处理函数

#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QDebug>

class A : public QWidget
{
public:
    void mousePressEvent(QMouseEvent *event){
        qDebug() << "mouse pressed";
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "mouse release";
    }
};

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

    A test;
    test.resize(400, 400);
    test.show();

    return a.exec();
}

这种方式比较简单,鼠标的信息,比如按下左键、右键、位置信息…可以看QMouseEvent中提供的方法。
2、重写event函数

#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QDebug>

class A : public QWidget
{
public:
    bool event(QEvent *event){
        if(event->type() == QEvent::MouseButtonPress){
            qDebug() << "QEvent KeyPress";
            return 1;
        }
        if(event->type() == QEvent::MouseButtonRelease){
            qDebug() << "QEvent KeyRelease";
            return QWidget::event(event);
        }
    }
    void mousePressEvent(QMouseEvent *event){
        qDebug() << "mouse pressed";
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "mouse release";
    }
};

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

    A test;
    test.resize(400, 400);
    test.show();

    return a.exec();
}

这里运行代码,点击鼠标打印信息如下:
在这里插入图片描述
可见mousePressEvent这个函数没有执行,主要是我们之间返回了没有将事件继续交由父类QWidget处理。
3、重写notify函数(不建议使用,这里举例只是为了说明整个事件处理流程)

#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QDebug>

class A : public QWidget
{
public:
    bool event(QEvent *event){
        if(event->type() == QEvent::MouseButtonPress){
            qDebug() << "QEvent KeyPress";
            return 1;
        }
        if(event->type() == QEvent::MouseButtonRelease){
            qDebug() << "QEvent KeyRelease";
            return QWidget::event(event);
        }
    }
    void mousePressEvent(QMouseEvent *event){
        qDebug() << "mouse pressed";
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "mouse release";
    }
};

class B : public QApplication
{
public:
    B(int argc, char *argv[]):QApplication(argc, argv){}
    bool notify(QObject *object, QEvent *event){
        if(event->type() == QEvent::MouseButtonPress){
            qDebug() << "notify QEvent::KeyPress";
        }
        if(event->type() == QEvent::MouseButtonRelease){
            qDebug() << "notify QEvent::KeyRelease";
        }
        return QApplication::notify(object, event);
    }
};

int main(int argc, char *argv[])
{
    B a(argc, argv);

    A test;
    test.resize(400, 400);
    test.show();

    return a.exec();
}

运行代码,点击鼠标打印信息如下:
在这里插入图片描述
可以看到输出信息跟信息传递描述的流程是一致的。
4、事件过滤器
使用事件过滤器主要有两个步骤,一是重写事件过滤这个函数,二是为需要使用事件过滤的控件安装事件过滤器。代码如下

#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QDebug>
#include <QPushButton>

class A : public QWidget
{
public:
    bool event(QEvent *event){
        if(event->type() == QEvent::MouseButtonPress){
            qDebug() << "QEvent KeyPress";
            return QWidget::event(event);
        }
        if(event->type() == QEvent::MouseButtonRelease){
            qDebug() << "QEvent KeyRelease";
            return QWidget::event(event);
        }
    }
    void mousePressEvent(QMouseEvent *event){
        qDebug() << " widget mouse pressed";
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "widget mouse release";
    }
};

class B : public QPushButton
{
public:
    B(QString text):QPushButton(text){}
    void mousePressEvent(QMouseEvent *event){
        qDebug() << "pushbutton mouse pressed";
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "pushbutton mouse release";
    }
};

class filter : public QObject
{
public:
    bool eventFilter(QObject *watched, QEvent *event){
        if(event->type() == QEvent::MouseButtonPress){
            qDebug() << watched->objectName() << ":mouse press";
            return 0;
        }
        if(event->type() == QEvent::MouseButtonRelease){
            qDebug() << watched->objectName() << ":mouse release";
            return 0;
        }
        return 0;
    }
};

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

    A test;
    B button1(QString("button1"));
    filter fi;
    test.setObjectName(QString("widget"));
    button1.setParent(&test);
    button1.setObjectName(QString("button1"));
    button1.move(100, 200);

    test.installEventFilter(&fi);
    button1.installEventFilter(&fi);
    test.resize(400, 400);
    test.show();

    return a.exec();
}

运行程序,依次点击widget界面和按钮,输出信息如下
在这里插入图片描述

由1可以看到过滤器是在event()前进行处理的,eventFilter中返回1表示该事件不再进一步进行处理,也就不会传到event中去;返回0表示交给目标对象处理。目前这里返回值为1,所以会继续传递。这里与event()中返回值含义类似。

四、事件接收和忽略

接收事件QEvent::accept(),忽略事件QEvent::ignore(),接收事件后事件将不再继续传递,这里我们用个例子看看。

#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QDebug>
#include <QPushButton>
#include <QMouseEvent>

class A : public QWidget
{
public:
    bool event(QEvent *event){
        if(event->type() == QEvent::MouseButtonPress){
            qDebug() << "QEvent KeyPress";
            return QWidget::event(event);
        }
        if(event->type() == QEvent::MouseButtonRelease){
            qDebug() << "QEvent KeyRelease";
            return QWidget::event(event);
        }
    }
    void mousePressEvent(QMouseEvent *event){
        qDebug() << " widget mouse pressed";
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "widget mouse release";
    }
};

class B : public QPushButton
{
public:
    B(QString text):QPushButton(text){}
    void mousePressEvent(QMouseEvent *event){
        qDebug() << "pushbutton mouse pressed";
        event->accept();
    }
    void mouseReleaseEvent(QMouseEvent *event){
        qDebug() << "pushbutton mouse release";
        event->accept();
    }
};

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

    A mainWidget;
    B button(QString("button"));

    mainWidget.setObjectName(QString("main widget"));

    button.setParent(&mainWidget);
    button.move(100, 200);

    mainWidget.resize(400, 400);
    mainWidget.show();

    return a.exec();
}

我们点击按钮后打印如下
在这里插入图片描述
主要是因为我们在B类中接受了鼠标事件,我们将event->accept();改成event->ignore();后运行点击按钮,输出信息如下
在这里插入图片描述
可以看到信号传到了父对象中,这里只有两层,如果有多层关系的话也是类似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

复杂的世界311

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值