Qt中的事件(3)- 自定义事件

原创
2022-11-25
4861
19

1. 自定义事件步骤

有时为了开发需要,我们希望自定义事件来完成某种目的。实现自定义事件的步骤如下:

  1. 继承QEvent。
  2. 定义事件类型(取值在QEvent::User和QEvent::MaxUser之间,建议使用registerEventType()函数自动创建一个全局唯一一个的事件类型,防止重复)
  3. 使用sendEvent()或postEvent()发送事件。
  4. 需要在自定义类中重写QObject::event()方法处理自定义事件。

2. 自定义事件类

自定义的事件类代码如下:

头文件

// -------------------------- 自定义事件 --------------------------------
class CustomerEvent : public QEvent
{
public:
    CustomerEvent(QString valueString = "");
    ~CustomerEvent();

    static Type eventType();
    QString getValueString(void);

private:
    static Type m_EventType;
    QString m_String;
};

源文件

QEvent::Type CustomerEvent::m_EventType = QEvent::None;

CustomerEvent::CustomerEvent(QString valueString) : QEvent(eventType())
{
    m_String = valueString;
}

CustomerEvent::~CustomerEvent()
{

}

QEvent::Type CustomerEvent::eventType()
{
    // 创建事件Type
    if (m_EventType == QEvent::None)
        m_EventType = (QEvent::Type)QEvent::registerEventType();

    return m_EventType;
}

QString CustomerEvent::getValueString(void)
{
    return m_String;
}

这里使用了CustomerEvent::eventType()函数为事件创建了类型。


3. 发送事件

发送事件有两种方法,一种是使用sendEvent()函数,一种是使用postEvent()函数。

3.1 sendEvent方法
sendEvent()方法是阻塞的,它发送个对象事件,等待接受对象处理结束后返回。函数原型如下:
static bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event);
参数: receiver为接受事件的对象, event为传递的事件指针
返回值:若事件被处理返回true, 否则返回false。
说明: 这个函数需要手动去释放事件的内存。
3.2 postEvent方法
postEvent()为异步的方法,它向事件队列中登记一个指定接收者的事件,然后返回。函数原型如下:
static void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority);
参数:receiver为接受事件的对象, event为传递的事件指针, priority为优先级
说明:这个函数不需要手动去释放事件的内存,有Qt框架自动释放。

使用PostEvent和SendEvent的例子如下:

头文件

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    virtual bool event(QEvent *event) override;
};

这里定义了一个Widget, 其中event()函数后面处理自定义事件时会用到。

源文件

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    // 创建按钮并布局
    QPushButton *button = new QPushButton("CreateEvent", this);
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(button);
    this->setGeometry(100, 100, 800, 600);

    // 建立连接, 发送信号
    QObject::connect(button, &QPushButton::clicked, [=](void)->void{
        // 使用PostEvent方式发送
        CustomerEvent *customerEvent = new CustomerEvent("PostCustomerEvent");
        QCoreApplication::postEvent(this, customerEvent);

        // 使用SendEvent方式发送
        CustomerEvent *sendCustomerEvent = new CustomerEvent("SendCustomerEvent");
        bool result = QCoreApplication::sendEvent(this, sendCustomerEvent);
        qDebug() << "The Dispose Result Is " << result;
        delete sendCustomerEvent;
    });
}

Widget::~Widget()
{

}

这里创建了一个按钮,当按钮按下时发送自定义的事件。


4. 事件处理

通过重写QObject::event()的方式处理自定义事件。代码如下:
bool Widget::event(QEvent *event)
{
    if (event->type() == CustomerEvent::eventType())
    {
        CustomerEvent *customerEvent = dynamic_cast<CustomerEvent*>(event);
        qDebug() << customerEvent->getValueString();
        return true;
    }
    return QWidget::event(event);
}

函数的返回true表示已经处理了此事件,否则返回false。

整体程序的运行结果为:
“SendCustomerEvent”
The Dispose Result Is true
“PostCustomerEvent”
可见,函数先处理了sendEvent()函数的事件, 等事件循环运行时分发给当前对象后处理。

不会飞的纸飞机
扫一扫二维码,了解我的更多动态。

下一篇文章:Qt中的属性系统