Qt 自定义event

本文章从属于 Qt实验室-CSDN博客系列

自定义事件携带数据

在某些情况下,可能需要通过事件携带一些额外的数据

可以通过自定义事件类来完成

一种实现方法是自定义一个QObject的子类,通过property来携带数据

复制代码
class MyEvent : public QObject,public QEvent
{
    Q_OBJECT
public:
    explicit MyEvent(QEvent::Type type,QObject *parent = nullptr);
}

这里通过一个自定义的窗口来发送自定义的事件,通过 QApplication::sendEvent(parent,evn);将事件传递给它的父窗口

复制代码
MyWidget::MyWidget(QWidget *parent)
    : QWidget{parent}
{
    QTimer* timer=new QTimer(this);
    timer->setInterval(1000);
    connect(timer,&QTimer::timeout,[=]{
        MyEvent* evn=new MyEvent(QEvent::Type(QEvent::User+101),this);
        evn->setProperty("x","1");
        evn->setProperty("y","2");
        //sendEvent阻塞式发送信号
        //发出去的信号需要接收者通过event()进行处理
        QApplication::sendEvent(parent,evn);
//        QApplication::postEvent(parent,evn);
    });
    timer->start();
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(500,300);

    MyWidget* center=new MyWidget(this);
    m_center=center;

    this->setCentralWidget(center);
}

在父窗口中通过event()去处理事件,并且获得事件中携带的数据

复制代码
bool MainWindow::event(QEvent *event)
{
    if(event->type()==QEvent::Type(QEvent::User+101))
    {
        //需要dynamic_cast,qobject_cast会编译不过
//        MyEvent* eve=qobject_cast<MyEvent*>(event);
        MyEvent* eve=dynamic_cast<MyEvent*>(event);
        qDebug()<<eve->property("x")<<","<<eve->property("y");
        qDebug()<<"in event :"<<"...";
        return true;
    }
    return true;
}

sendEvent阻塞式与postEvent队列式

这里,QApplication::sendEvent(parent,evn)后,会立刻进入MainWindow::event()中去进行处理;

QApplication::postEvent(parent,evn);则是将事件放入队列后,立刻就返回了

复制代码
MyWidget::MyWidget(QWidget *parent)
    : QWidget{parent}
{
    QTimer* timer=new QTimer(this);
    timer->setInterval(1000);
    connect(timer,&QTimer::timeout,[=]{
        MyEvent* evn=new MyEvent(QEvent::Type(QEvent::User+101),this);
        evn->setProperty("x","1");
        evn->setProperty("y","2");
        //sendEvent阻塞式发送信号
        //发出去的信号需要接收者通过event()进行处理
//        QApplication::sendEvent(parent,evn);
        QApplication::postEvent(parent,evn);
        qDebug()<<"after send";

    });
    timer->start();
}

bool MainWindow::event(QEvent *event)
{

    if(event->type()==QEvent::Type(QEvent::User+101))
    {
        QThread::sleep(2);
        //需要dynamic_cast,qobject_cast会编译不过
//        MyEvent* eve=qobject_cast<MyEvent*>(event);
        MyEvent* eve=dynamic_cast<MyEvent*>(event);
//        QObject* eve=qobject_cast<QObject*>(event);
        qDebug()<<eve->property("x")<<","<<eve->property("y");
        qDebug()<<"in event :"<<"...";
        return true;
    }
    return false;
}

以上代码中,当使用 QApplication::sendEvent(parent,evn);时,打印的顺序是:

QVariant(QString, "1") , QVariant(QString, "2")

in event : ...

after send

当使用QApplication::postEvent(parent,evn);时,打印的顺序是:

after send

QVariant(QString, "1") , QVariant(QString, "2")

in event : ...

简单分析一下,当使用sendEvent发送事件时,会立刻进入到MainWindow::event(),从而打印QVariant(QString, "1") , QVariant(QString, "2")

in event : ...

从MainWindow::event()结束返回后,再回到QApplication::sendEvent()后面打印after send

体现了sendEvent的阻塞模式;

而使用postEvent发送事件时,会将事件放入队列,然后postEvent()返回了,于是打印了after send

等到事件队列处理了事件的时候,才会打印QVariant(QString, "1") , QVariant(QString, "2")

in event : ...

体现了postEvent的队列模式

但这里尽管发送事件的频率是1次/s,处理事件的频率是1次/2s,而使用postEvent发送事件时打印的after send和in event : ...依然是一一对应的。

这是因为发送事件和处理事件在同一个线程内,只有处理完了一个事件之后,timer才会继续下一个计时。

假如发送事件和处理事件不再同一个线程内,那么after send和in event : ...将不会一一对应。

相关推荐
Mr_Xuhhh7 分钟前
信号与槽的总结
java·开发语言·数据库·c++·qt·系统架构
纳兰青华17 分钟前
bean注入的过程中,Property of ‘java.util.ArrayList‘ type cannot be injected by ‘List‘
java·开发语言·spring·list
好开心啊没烦恼20 分钟前
Python 数据分析:DataFrame,生成,用字典创建 DataFrame ,键值对数量不一样怎么办?
开发语言·python·数据挖掘·数据分析
liulilittle22 分钟前
VGW 虚拟网关用户手册 (PPP PRIVATE NETWORK 基础设施)
开发语言·网络·c++·网关·智能路由器·路由器·通信
Devil枫32 分钟前
Kotlin高级特性深度解析
android·开发语言·kotlin
ChinaDragonDreamer34 分钟前
Kotlin:2.1.20 的新特性
android·开发语言·kotlin
安之若素^1 小时前
启用不安全的HTTP方法
java·开发语言
一个天蝎座 白勺 程序猿1 小时前
Python(28)Python循环语句指南:从语法糖到CPython字节码的底层探秘
开发语言·python
持梦远方2 小时前
C 语言基础入门:基本数据类型与运算符详解
c语言·开发语言·c++
zzywxc7872 小时前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring