QT事件过滤器

QT事件过滤器

事件过滤器(Event Filter)是一种强大的机制,允许你在事件到达目标对象之前拦截和处理这些事件。事件过滤器可以用于全局事件处理、调试、性能优化等多种场景。

事件过滤器是一个实现了 QObject::eventFilter 虚函数的对象。通过调用 QObject::installEventFilter 方法,可以将事件过滤器安装到目标对象上。当目标对象接收到事件时,事件会首先传递给事件过滤器进行处理。

实现步骤:

1. 创建事件过滤器类: 创建一个继承自 QObject 的类,并重写 eventFilter 方法。
 
    class MyEventFilter : public QObject {
        Q_OBJECT
    public:
        MyEventFilter(QObject *parent = nullptr);
    protected:
        bool eventFilter(QObject *watched, QEvent *event) override;
    };

2. 实现 eventFilter 方法: 在 eventFilter 方法中处理你感兴趣的事件,并决定是否继续传递事件给目标对象。

    bool MyEventFilter::eventFilter(QObject *watched, QEvent *event) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Tab) {
                // 处理 Tab 键事件
                qDebug() << "Tab key pressed";
                return true; // 阻止事件继续传递
            }
        }
        return QObject::eventFilter(watched, event); // 继续传递事件
    }

3. 安装事件过滤器: 使用 QObject::installEventFilter 方法将事件过滤器安装到目标对象上。

    MyEventFilter *filter = new MyEventFilter(this);
    QLineEdit *lineEdit = new QLineEdit(this);
    lineEdit->installEventFilter(filter);


性能影响:事件过滤器可能会影响应用程序的性能,特别是在处理大量事件时。因此,应谨慎使用事件过滤器,并确保其逻辑尽可能高效。

事件传递顺序:事件过滤器在目标对象的 event 方法之前调用。如果事件过滤器返回 true,事件将不会传递给目标对象。

移除事件过滤器:可以使用 QObject::removeEventFilter 方法移除已安装的事件过滤器。

引例

#include <QApplication>
#include <QLineEdit>
#include <QDebug>
#include <QEvent>
#include <QKeyEvent>

class MyEventFilter : public QObject {
    Q_OBJECT
public:
    MyEventFilter(QObject *parent = nullptr) : QObject(parent) {}
protected:
    bool eventFilter(QObject *watched, QEvent *event) override {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Tab) {
                qDebug() << "Tab key pressed";
                return true; // 阻止事件继续传递
            }
        }
        return QObject::eventFilter(watched, event); // 继续传递事件
    }
};

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

    QLineEdit lineEdit;
    MyEventFilter filter;
    lineEdit.installEventFilter(&filter);

    lineEdit.show();
    return app.exec();
}

#include "main.moc"

示例

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QImage>//此类用于加载图片
#include <QMouseEvent>
#include <QEvent>
#include <QBoxLayout>
#include <QTransform>//二维变换矩阵

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;


private:

    QLabel *label1img;
    QLabel *label2img;
    QLabel *label3img;

    QLabel *label;
    QImage img1;
    QImage img2;
    QImage img3;

public:
    //重写 eventFilter 方法

    bool eventFilter(QObject *obj, QEvent *event) override;

};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //删除当前布局Layout
    QLayout *layout = this->layout();
    if (layout!= nullptr) {
        delete layout;
    }
    setWindowTitle("事件过滤器");

    label = new QLabel("状态提示");//状态提示
    label->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);//设置图片居中
    label1img = new QLabel();
    label1img->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);//设置图片居中
    label2img = new QLabel();
    label2img->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);//设置图片居中
    label3img = new QLabel();
    label3img->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);//设置图片居中

    img1.load("D:/1.png");//图片1
    img2.load("D:/1.png");//图片2
    img3.load("D:/1.png");//图片3
    label1img->setPixmap(QPixmap::fromImage(img1));//设置图片1
    label2img->setPixmap(QPixmap::fromImage(img2));//设置图片2
    label3img->setPixmap(QPixmap::fromImage(img3));//设置图片3

    QHBoxLayout *la = new QHBoxLayout();
    la->addWidget(label1img);
    la->addWidget(label2img);
    la->addWidget(label3img);

    QVBoxLayout *layout1 = new QVBoxLayout(this);//设置布局
    layout1->addWidget(label);
    layout1->addLayout(la);


    //安装事件过滤器
    label1img->installEventFilter(this);
    label2img->installEventFilter(this);

    label3img->installEventFilter(this);

}

MainWindow::~MainWindow()
{
    delete ui;
}

//事件过滤
//@param obj 接收事件的对象
//@param event 事件对象
//返回值:true表示事件被处理,false表示事件未被处理
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
    if (obj == label1img) {
        if (event->type() == QEvent::MouseButtonPress) { //鼠标按下事件
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); //转换为鼠标事件
            if (mouseEvent->button() == Qt::LeftButton) {
                label->setText("鼠标左键点击图片1");
            }else if (mouseEvent->button() == Qt::RightButton) {
                label->setText("鼠标右键点击图片1");
            }else if (mouseEvent->button() == Qt::MiddleButton) {
                label->setText("鼠标中键点击图片1");
            }
            //放大图片
            QTransform  transform;//设置变换
            transform.scale(1.5, 1.5);//放大倍数
            label1img->setPixmap(label1img->pixmap().transformed(transform));//设置图片

        }
        else if (event->type() == QEvent::MouseButtonRelease) { //鼠标释放事件
            label->setText("鼠标释放图片1");
            //还原图片
            label1img->setPixmap(QPixmap::fromImage(img1));//设置图片

        }
    }
    if (obj == label2img) {
        if (event->type() == QEvent::MouseButtonPress) { //鼠标按下事件
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); //转换为鼠标事件
            if (mouseEvent->button() == Qt::LeftButton) {
                label->setText("鼠标左键点击图片1");
            }else if (mouseEvent->button() == Qt::RightButton) {
                label->setText("鼠标右键点击图片1");
            }else if (mouseEvent->button() == Qt::MiddleButton) {
                label->setText("鼠标中键点击图片1");
            }
            //放大图片
            QTransform  transform;//设置变换
            transform.scale(1.5, 1.5);//放大倍数
            label2img->setPixmap(label2img->pixmap().transformed(transform));//设置图片

        }
        else if (event->type() == QEvent::MouseButtonRelease) { //鼠标释放事件
            label->setText("鼠标释放图片2");
            //还原图片
            label2img->setPixmap(QPixmap::fromImage(img2));//设置图片

        }
    }

    return QMainWindow::eventFilter(obj, event);//先交给父类处理
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

可能只会写BUG

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

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

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

打赏作者

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

抵扣说明:

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

余额充值