QT中事件及事件处理

QT中事件及事件处理

什么是事件,事件与Qt中信号的区别?

个人所见:
事件是应用程序对内部或者外部的动作的统称。
信号是事件的后续响应通知
例如你点击了一个按钮,物理上的鼠标点击动作就是事件,而程序收到事件时,就会发出按钮被按下的信号,通知按钮被按下了。
常见的事件有:鼠标事件,定时事件,键盘事件,关闭事件,上下文菜单事件,拖放事件。

QT事件封装

在Qt中,事件作为一个对象,继承自QEvent类,常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent等,它们与QEvent类的继承关系如图所示:
在这里插入图片描述

事件的处理方式

方法一:重新实现部件的paintEvent(),mousePressEvent()等事件处理函数。这是最常用也的一种方法,不过它只能用来处理特定部件的特定事件。例如前一章实现拖放操作,就是用的这种方法。

方法二:重新实现notify()函数。这个函数功能强大,提供了完全的控制,可以在事件过滤器得到事件之前就获得它们。但是,它一次只能处理一个事件。

方法三:向QApplication对象上安装事件过滤器。因为一个程序只有一个QApplication对象,所以这样实现的功能与使用notify()函数是相同的,优点是可以同时处理多个事件。

方法四:重新实现event()函数。QObject类的event()函数可以在事件到达默认的事件处理函数之前获得该事件。

方法五:在对象上安装事件过滤器。使用事件过滤器可以在一个界面类中同时处理不同子部件的不同事件。

实际编程中,最常用的是方重新实现event函数,其次是事件过滤器。

具体事件处理方式

重新实现事件处理函数

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
#include <QDebug>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
protected:
    void keyPressEvent(QKeyEvent *event) override;
};

class MyLineEdit:public QLineEdit
{
     Q_OBJECT
public:
    MyLineEdit(QWidget *parent):QLineEdit(parent){};
    ~MyLineEdit();
protected:
    void keyPressEvent(QKeyEvent *event) override;
};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include <QKeyEvent>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    MyLineEdit * line = new MyLineEdit(parent);
    setCentralWidget(line);
}

MainWindow::~MainWindow()
{

}

 void MainWindow::keyPressEvent(QKeyEvent * event)
{
    qDebug() << "MainWindow key PressEvent";

}

 void MyLineEdit::keyPressEvent(QKeyEvent * event)
{

    qDebug() << "MyLineEdit key PressEvent";
    QLineEdit::keyPressEvent(event);

}

MyLineEdit::~MyLineEdit()
{

}

执行结果:
在这里插入图片描述
MyLineEdit中添加ignore;

 void MyLineEdit::keyPressEvent(QKeyEvent * event)
{

    qDebug() << "MyLineEdit key PressEvent";
    QLineEdit::keyPressEvent(event);
    event->ignore(); //忽略该事件
}

执行结果:
在这里插入图片描述
结论:
从例子中可以看到,事件是先传递给指定窗口部件的。
这里确切的说应该是先传递给获得焦点的窗口部件的。
但是如果该部件忽略掉该事件(ignore),那么这个事件就会传递给这个部件的父部件。
在重新实现事件处理函数时,一般要调用父类的相应的事件处理函数来实现默认的操作。

安装事件过滤器

1在MyLineEdit中添加函数声明:
bool event(QEvent *event);
该函数定义:

bool MyLineEdit::event(QEvent * event)
{
    if(event->type() == QKeyEvent::KeyPress)
    {
        qDebug() << "MyLineEdit event";
    }
    return QLineEdit::event(event);//执行QLineEdit类event()函数的默认操作
}

在MyLineEdit的event()函数中使用了QEvent的type()函数来获取事件的类型,如果是键盘按下事件QEvent::KeyPress,则输出信息。因为event()函数具有bool型的返回值,所以在该函数的最后要使用return语句,这里一般是返回父类的event()函数的操作结果。

2 事件过滤器函数的声明:
bool eventFilter(QObject *obj, QEvent *event);
构造函数的最后添上一行代码:

MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)
{
    installEventFilter(this);
}

事件过滤器函数的定义:

bool MyLineEdit::eventFilter(QObject *obj, QEvent *event) // 事件过滤器
{
  if(obj == this) {              // 如果本部件上的事件
        if(event->type() == QEvent::KeyPress)
        qDebug() << tr("事件过滤器");
   }
  return QWidget::eventFilter(obj, event);
}

在事件过滤器中,先判断该事件的对象是不是本身,如果是,再判断事件类型。最后返回了QWidget默认的事件过滤器的执行结果。
执行结果:
在这里插入图片描述
完整代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
#include <QDebug>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
protected:
    void keyPressEvent(QKeyEvent *event) override;
};

class MyLineEdit:public QLineEdit
{
     Q_OBJECT
public:
    MyLineEdit(QWidget *parent);
    ~MyLineEdit();
    bool eventFilter(QObject *obj, QEvent *event) override;
protected:
    void keyPressEvent(QKeyEvent *event) override;
    bool event(QEvent *event) override; //重新实现event函数
};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include <QKeyEvent>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    MyLineEdit * line = new MyLineEdit(parent);
    setCentralWidget(line);
}

MainWindow::~MainWindow()
{

}

 void MainWindow::keyPressEvent(QKeyEvent * event)
{
    qDebug() << "MainWindow key PressEvent";

}
MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)
{
    installEventFilter(this); //安装事件过滤器
}
 void MyLineEdit::keyPressEvent(QKeyEvent * event)
{

    qDebug() << "MyLineEdit key PressEvent";
    QLineEdit::keyPressEvent(event);
    event->ignore();
}
bool MyLineEdit::event(QEvent * event)
{
    if(event->type() == QKeyEvent::KeyPress)
    {
        qDebug() << "MyLineEdit event";
    }
    return QLineEdit::event(event);

}

bool MyLineEdit::eventFilter(QObject *obj, QEvent *event) // 事件过滤器
{
  if(obj == this) {              // 如果本部件上的事件
        if(event->type() == QEvent::KeyPress)
        qDebug() << tr("事件过滤器");
   }
  return QLineEdit::eventFilter(obj, event);
}

MyLineEdit::~MyLineEdit()
{

}

事件的传递

在每个程序的main()函数的最后,都会调用QApplication类的exec()函数,它会使Qt应用程序进入事件循环,这样就可以使应用程序在运行时接收发生的各种事件。一旦有事件发生,Qt便会构建一个相应的QEvent子类的对象来表示它,然后将它传递给相应的QObject对象或其子对象。

从前面的例子可以看到,事件的传递顺序是这样的:先是事件过滤器,然后是该部件的event()函数,最后是该部件的事件处理函数。这里还要注意,event()函数和事件处理函数,是在该部件内进行重新定义的,而事件过滤器却是在该部件的父部件中进行定义的(但我在子类中定义也可以)。

传递图:
在这里插入图片描述
事件传递过程是:就近,焦点原则(谁在交互,就是谁),子部件响应后的事件可以传递父部件。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 事件处理机制是基于事件驱动的,主要分为以下几个部分: 1. 事件循环(Event Loop):Qt 应用程序通过事件循环来等待事件的发生。事件循环是一个无限循环,等待事件的发生,当有事件发生时,将事件传递给相应的对象进行处理。 2. 事件(Event):事件Qt 应用程序的基本单位,例如鼠标点击、键盘按键等。在 Qt 事件被封装成 QEvent 类,不同类型的事件对应不同的 QEvent 类型。 3. 事件过滤器(Event Filter):事件过滤器是一个对象,用于拦截和处理其他对象的事件事件过滤器可以在事件到达目标对象之前对事件进行预处理,也可以在事件到达目标对象之后对事件进行后处理。 4. 事件处理器(Event Handler):事件处理器是一个对象,用于处理自己接收到的事件。每个对象都可以有自己的事件处理器,用于处理特定类型的事件。在 Qt 事件处理器通常是通过重写 QObject 类的事件处理函数来实现的。 5. 事件分发(Event Dispatch):在事件循环,当事件到达目标对象时,Qt事件分发给目标对象的事件处理器进行处理。如果目标对象没有事件处理器,事件将被传递给目标对象的父对象进行处理,直到事件被处理或者到达应用程序的根对象为止。 总的来说,Qt 事件处理机制是一种高效、灵活和可扩展的事件驱动模型,可以帮助开发者轻松地处理各种事件,实现各种功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值