Qt之自定义QEvent

1、要创建自定义类型的事件,首先需要定义一个类似于QEvent::KeyPress、QEvent::KeyRelease事件类型,并且该事件类型的值必须大于QEvent::User。然后再子类化QEvent,在子类中实现相关的函数。最后再调用QCoreApplication::postEvent()或者QApplication::sendEvent()。

2、如何定义个事件类型。Qt中提供了[static] int QEvent::registerEventType(int hint = -1)用来定义程序中唯一的事件类型。

3、由于QCoreApplication::postEvent()或者QApplication::sendEvent()是线程安全的,所以在多线程中也可以正常使用。

4、postEvent和sendEvent的区别:

    1)sendEvent使用notify()函数直接给receiver发送事件。(不支持多线程、event变量直接在堆栈上生成,在发送事件时,不会删除该事件)

    2)postEvent 向事件队列中添加receiver和event,对应异步处理事件。(支持多线程,event必须在堆上分配,因为post事件队列将获得事件的所有权,并在事件被post后删除它)

5、自定义事件可以用来干嘛。

    1)用于对象间的通信

#include "widget.h"
#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QEvent>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLineEdit>

//注册两个事件类型
static QEvent::Type g_Widget1_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
static QEvent::Type g_Widget2_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());

class MyEvent : public QEvent
{
public:
    MyEvent(QEvent::Type type):QEvent(type)
    {
        m_message = "";
    }
    ~MyEvent()
    {
        qDebug() << __FUNCTION__;
    }

    void setMessage(const QString &msg)
    {
        m_message = msg;
    }

    QString getMessage()const
    {
        return m_message;
    }
private:
    QString m_message;
};

class Widget1:public QWidget
{
    Q_OBJECT
public:
    Widget1()
    {
        setWindowTitle("Widget1");
        QHBoxLayout *layout = new QHBoxLayout;
        QPushButton *button = new QPushButton("发送");
        layout->addWidget(button);
        QLineEdit *edit = new QLineEdit;
        layout->addWidget(edit);

        connect(button,&QPushButton::clicked,[=]{
//            MyEvent *event = new MyEvent(g_Widget1_eventType);
//            event->setMessage(edit->text());
//            QApplication::postEvent(m_receiver,event);
            MyEvent event(g_Widget1_eventType);
            event.setMessage(edit->text());
            QApplication::sendEvent(m_receiver,&event);
            qDebug() << "发送信号";
        });

        QVBoxLayout *mainLayout = new QVBoxLayout;
        mainLayout->addLayout(layout);
        m_label = new QLabel("等待接收信息...");
        mainLayout->addWidget(m_label);
        setLayout(mainLayout);
    }
    void setRecevier(QObject *receiver)
    {
        m_receiver = receiver;
    }
protected:
    bool event(QEvent *event)
    {
        if(event->type() == g_Widget2_eventType){
            qDebug() << "111";
            MyEvent *e = static_cast<MyEvent*>(event);
            m_label->setText(e->getMessage());
            return true;
        }
        return QWidget::event(event);
    }
private:
    QLabel *m_label;
    QObject *m_receiver;
};

class Widget2:public QWidget
{
    Q_OBJECT
public:
    Widget2()
    {
        setWindowTitle("Widget2");
        QHBoxLayout *layout = new QHBoxLayout;
        QPushButton *button = new QPushButton("发送");
        layout->addWidget(button);
        QLineEdit *edit = new QLineEdit;
        layout->addWidget(edit);

        connect(button,&QPushButton::clicked,[=]{
//            MyEvent *event = new MyEvent(g_Widget2_eventType);
//            event->setMessage(edit->text());
//            QApplication::postEvent(m_receiver,event);
            MyEvent event(g_Widget2_eventType);
            event.setMessage(edit->text());
            QApplication::sendEvent(m_receiver,&event);
            qDebug() << "发送信号";
        });

        QVBoxLayout *mainLayout = new QVBoxLayout;
        mainLayout->addLayout(layout);
        m_label = new QLabel("等待接收信息...");
        mainLayout->addWidget(m_label);
        setLayout(mainLayout);

    }
    void setRecevier(QObject *receiver)
    {
        m_receiver = receiver;
    }
protected:
    bool event(QEvent *event)
    {
        if(event->type() == g_Widget1_eventType){
            qDebug() << "222";
            MyEvent *e = static_cast<MyEvent*>(event);
            m_label->setText(e->getMessage());
            return true;
        }
        QWidget::event(event);
    }
private:
    QLabel *m_label;
    QObject *m_receiver;
};

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

    Widget1 w1;
    Widget2 w2;

    w1.setRecevier(&w2);
    w2.setRecevier(&w1);

    w1.show();
    w2.show();

    return a.exec();
}

#include "main.moc"

    2)多线程编程

#include <QApplication>
#include <QThread>
#include <QWidget>
#include <QDebug>
#include <QProgressBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>

#include <QEvent>

//自定义全局事件类型
static const QEvent::Type g_request_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
static const QEvent::Type g_respond_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());

class DownEvent : public QEvent
{
  public:
    DownEvent(QEvent::Type type):QEvent(type)
    {

    }
    ~DownEvent()
    {
        qDebug() << __FUNCTION__;
    }
    void setData(const QString data)
    {
        m_data = data;
    }

    QString getData()const
    {
        return m_data;
    }

    void setProgress(int data)
    {
        m_process = data;
    }

    int getProgress()const
    {
        return m_process;
    }

    void setReceiver(QObject *receiver)
    {
        m_receiver = receiver;
    }

    QObject *getReceiver()
    {
        return m_receiver;
    }

private:
    QString m_data;
    int m_process;
    QObject *m_receiver;
};

class DownLoadThread : public QThread
{
public:
    DownLoadThread(){}
    ~DownLoadThread()
    {
        if(isRunning()){
            quit();
            wait();
        }
    }
protected:
    bool event(QEvent *event)
    {
        if(event->type() == g_request_eventType){
            DownEvent *e = static_cast<DownEvent*>(event);
            m_data = e->getData();
            m_receiver = e->getReceiver();
            if(!this->isRunning())
                this->start();
            return true;
        }
        return QThread::event(event);
    }
    void run()
    {
        for(int i = 1; i <= 100; ++i){
            msleep(500);
            DownEvent *event = new DownEvent(g_respond_eventType);
            event->setProgress(i);
            QApplication::postEvent(m_receiver,event);
        }
    }
private:
    QString m_data;
    QObject *m_receiver;
};

class Widget : public QWidget
{
  Q_OBJECT
public:
    Widget()
    {
        QVBoxLayout *mainLayout = new QVBoxLayout;
        QPushButton *button = new QPushButton("下载");
        connect(button,&QPushButton::clicked,[=]{
            DownEvent *event = new DownEvent(g_request_eventType);
            event->setData("xxxx.txt");
            event->setReceiver(this);
            QApplication::postEvent(m_receiver,event);
            button->setEnabled(false);
        });
        mainLayout->addWidget(button);
        m_bar = new QProgressBar;
        connect(m_bar,&QProgressBar::valueChanged,[=](int value){
            if(m_bar->maximum() == value)
                button->setEnabled(true);
        });
        m_bar->setRange(0,100);
        mainLayout->addWidget(m_bar);
        setLayout(mainLayout);
    }

    void setReceiver(QObject *receiver)
    {
        m_receiver = receiver;
    }

    bool event(QEvent *event)
    {
        if(event->type() == g_respond_eventType){
            DownEvent *e = static_cast<DownEvent*>(event);
            m_process = e->getProgress();
            qDebug() << m_process;
            m_bar->setValue(m_process);
            return true;
        }
        return QWidget::event(event);
    }
private:
    int m_process;
    QObject *m_receiver;
    QProgressBar *m_bar;
};

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

    DownLoadThread thread;
    Widget w;
    w.show();
    w.setReceiver(&thread);

    return a.exec();
}

#include "main.moc"

猜你喜欢

转载自blog.csdn.net/wei375653972/article/details/86620229