发送自定义事件

Qt 可以在程序中自主发送事件

阻塞型事件发送

  • 事件发送后需要等待事件处理完成

非阻塞型事件发送

  • 事件发送后立即返回
  • 事件被分发到事件队列等待处理

QApplication 类提供了事件发送的静态成员函数

阻塞型发送函数:

  • bool sendEvent(QObject* receiver,QEvent* event);

非阻塞型发送函数:

  • bool postEvent(QObject* receiver,QEvent* event);

注意事项

sendEvent 中事件对象的生命周期由 Qt 程序管理

  • 同时支持栈事件对象和堆事件对象的发送

postEvent 中事件对象的生命周期由 Qt 程序管理

  • 只能发送堆事件对象
  • 事件处理后由 Qt 平台进行销毁

使用 sendEvent 发送事件对象

小贴士:消息发送过程可以理解为:在 sendEvent 函数内部直接调用 Qt 对象的 event() 事件处理函数。

使用 postEvent 发送事件对象

在程序中发送事件

Widget.h

class Widget : public QWidget
{
    Q_OBJECT
private:
    QPushButton m_Btn;

private slots:
    void onPushButtonClicked();

protected:
    void testSendEvent();
    void testPostEvent();
    bool event(QEvent* e);

public:
    Widget(QWidget* parent = nullptr);
    ~Widget();
};

Widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_Btn.setParent(this);

    connect(&m_Btn, &QPushButton::clicked, this, &Widget::onPushButtonClicked);
}

void Widget::onPushButtonClicked()
{
    testSendEvent();
    // testPostEvent();
}

void Widget::testSendEvent()
{
    QMouseEvent me(QEvent::MouseButtonDblClick,QPointF(1, 1), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);

    qDebug() << "before send event";

    QApplication::sendEvent(this, &me);

    qDebug() << "after send event";
}

void Widget::testPostEvent()
{
    QMouseEvent *me = new QMouseEvent(QEvent::MouseButtonDblClick,QPointF(1, 1), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);

    qDebug() << "before post event";

    QApplication::postEvent(this, me);

    qDebug() << "after post event";
}

bool Widget::event(QEvent *e)
{
    if(e->type() == QEvent::MouseButtonDblClick)
        qDebug() << "event : " << e;

    return QWidget::event(e);
}

Widget::~Widget()
{
}

首先测试 sendEvent,结果如下所示

测试 postEvent,结果如下所示

Qt 可以自定义新的事件类

自定义的事件类必须继承自 QEvent

自定义的事件类必须拥有全局唯一的 Type 值

程序中必须提供处理自定义事件对象的方法

自定义事件类

1. 将 QEvent 作为父类继承

2. 指定全局唯一的 Type 值

Qt 中事件的 Type 值

每个事件类都具有全局唯一的 Type 值

自定义事件类的 Type 值也需要自定义

自定义事件类使用 QEvent::User 之后的值作为 Type 值

程序中保证 QEvent::User + Value 全局唯一即可

处理自定义事件的方法

1. 将事件过滤器安装到目标对象

  • 在 EventFilter() 函数中编写自定义事件的处理逻辑

2. 在目标对象的类中重写事件处理函数

  • 在 event() 函数中编写自定义事件的处理逻辑

 发送和处理自定义事件

StringEvent.h

class StringEvent : public QEvent
{
private:
    QString m_data;

public:
    explicit StringEvent(QString data = 0);

    const static Type TYPE = static_cast<Type>(QEvent::User + 0xFF);

    void setData(QString data);
    QString data();

signals:

};

StringEvent.cpp

StringEvent::StringEvent(QString data) : QEvent(TYPE)
{
    m_data = data;
}

void StringEvent::setData(QString data)
{
    m_data = data;
}

QString StringEvent::data()
{
    return m_data;
}

Widget.h

class Widget : public QWidget
{
    Q_OBJECT
private:
    QLineEdit m_edit;

protected:
    bool event(QEvent* e);
    bool eventFilter(QObject* obj, QEvent* e);

public:
    Widget(QWidget* parent = nullptr);
    ~Widget();
};

Widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent), m_edit(this)
{
    m_edit.installEventFilter(this);

    resize(600, 400);
}

bool Widget::eventFilter(QObject *obj, QEvent *e)
{
    if((obj == &m_edit) && e->type() == StringEvent::TYPE)
    {
        StringEvent* se = dynamic_cast<StringEvent*>(e);

        qDebug() << "receive data : " << se->data();

        m_edit.insert(se->data());

        return true;
    }

    return QWidget::eventFilter(obj, e);
}

bool Widget::event(QEvent *e)
{
    if(e->type() == QEvent::MouseButtonDblClick)
    {
        StringEvent se("liujie");

        qDebug() << "before send event";

        QApplication::sendEvent(&m_edit, &se);

        qDebug() << "after send event";
    }
    
    return QWidget::event(e);
}

Widget::~Widget()
{
}

程序运行结果如下所示

为什么要自定义事件类?

需要拓展一个已有组件类的功能

需要开发一个全新功能的组件类

需要向一个第三方的组件类发送消息

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值