(三十)自定义事件

自主发送事件:

1、  阻塞型事件发送:

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

bool QCoreApplication::sendEvent ( QObject * receiver, QEvent * event ) [static]

 

2、非阻塞型事件发送:

         事件发送后立即返回

         事件被发送到事件队列中等待处理

         voidQCoreApplication::postEvent ( QObject * receiver, QEvent * event ) [static]

 

注意事项:

1、 sendEvent()中的事件对象的生命周期由Qt程序管理,支持栈事件对象与堆事件对象的发送

2、postEvent()中的事件对象的生命周期由Qt平台管理,只能发送堆事件对象,事件被处理后由Qt平台销毁

 

//Widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include 
#include 
 
class Widget : public QWidget
{
   Q_OBJECT
   
   QPushButton m_pushButton;
 
   void testSendEvent();
   void testPostEvent();
protected slots:
   void onButtonClicked();
public:
   Widget(QWidget *parent = 0);
   bool event(QEvent* evt);
   ~Widget();
};
 
#endif // WIDGET_H
 


 

//Widget.cpp


#include "Widget.h"
#include 
#include 
#include 
 
Widget::Widget(QWidget *parent)
    :QWidget(parent)
{
   m_pushButton.setParent(this);                //指定父子关系
   m_pushButton.setText("Test");
 
   connect(&m_pushButton, SIGNAL(clicked()), this,SLOT(onButtonClicked()));      
}
//槽函数相当于是在事件处理函数内部调用的,槽函数执行完之前,事件处理函数未执行完毕,即当前事件对象正在被处理
void Widget::onButtonClicked()      
{
   // testSendEvent();
   testPostEvent();
}
 
void Widget::testSendEvent()
{//定义事件对象,对象类型为鼠标双击事件,事件地点在0,0处,左键触发,后面两个参数指定鼠标与键盘的状态位
   QMouseEvent dbcEvt(QEvent::MouseButtonDblClick, QPoint(0, 0),Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
 
   qDebug() << "Before sendEvent()";
        
    QCoreApplication::sendEvent(this,&dbcEvt);                  //为阻塞式的
         //调用后的现象是为:下面的event()函数执行完毕后再打印的下面的"after sendevent",仿佛QCoreApplication::sendEvent函数直接调用了接收对象的event()函数
        
   qDebug() << "After sendEvent()";
}
 
void Widget::testPostEvent()
{                                                                                           
   QMouseEvent* dbcEvt = new QMouseEvent(QEvent::MouseButtonDblClick,QPoint(0, 0), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);      //postEvent函数只能发送堆事件对象
 
   qDebug() << "Before postEvent()";
                  
    QCoreApplication::postEvent(this,dbcEvt);//非阻塞式,调用后的现象是,打印完下面的"after postEvent"后才能看到event()函数被执行,事件被发送到了事件队列,需要根据事件队列中事件顺序依次处理事件
 
   qDebug() << "After postEvent()";
}
 
bool Widget::event(QEvent* evt)
{
   if( evt->type() == QEvent::MouseButtonDblClick ) 
    {
       qDebug() << "event(): " << evt;       
    }
 
   return QWidget::event(evt);  
}       
        
Widget::~Widget()
{
   
}



自定义事件

意图自定义的事件类:

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

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

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

 

步骤:

1、将QEvent作为父类继承

2、指定全局唯一的Type值

class XXXEvent : public QEvent                           //自定义的事件类必须继承自QEvent类
{
   QString m_data;
public:
//自定义事件类必须拥有全局唯一的事件Type值,且需使用QEvent::User之后的值
const staticType TYPE = static_cast(QEvent::User + 0xFF);       
 
       //…..                 
};


 

3、处理自定义事件的常用方法

1)、给目标对象安装事件过滤器,在eventFilter()函数中编写自定义事件处理逻辑

2)、在目标对象类中重写event(),在event()函数中编写自定义事件的处理逻辑

事件的Type值:

1、每个Qt事件类都拥有全局唯一的Type值

2、自定义的事件类的Type值需要自定义

3、自定义事件类使用QEvent::User之后的值作为Type值,QEvent::User+ Value

4、需要保证应用程序中的自定义事件类的Type值:QEvent::User + Value全局唯一

 

//StringEvent.h

 

#ifndef _STRINGEVENT_H_
#define _STRINGEVENT_H_
 
#include 
#include 
 
class StringEvent : public QEvent                       //自定义的事件类必须继承自QEvent类
{
   QString m_data;
public:
//自定义事件类必须拥有全局唯一的事件Type值,自定义事件需使用QEvent::User之后的值
   const static Type TYPE = static_cast(QEvent::User + 0xFF);       
                                                                                                                                                                       
   explicit StringEvent(QString data = "");           
   QString data();                  
   
};
 
#endif // _STRINGEVENT_H_
 
// StringEvent.cpp
 
#include "StringEvent.h"
 
StringEvent::StringEvent(QString data) :QEvent(TYPE)
{                                                      
   m_data = data;
}
 
QString StringEvent::data()
{
   return m_data;
}
 
//Widget.h
#ifndef WIDGET_H
#define WIDGET_H
 
#include 
#include 
 
class Widget : public QWidget
{
   Q_OBJECT
   
   QLineEdit m_edit;
public:
   Widget(QWidget *parent = 0);
   bool event(QEvent* evt);                                                       
   bool eventFilter(QObject* obj, QEvent* evt);
   ~Widget();
};
 
#endif // WIDGET_H


 

//Widget.cpp


#include "Widget.h"
#include "StringEvent.h"
#include 
#include 
#include 
 
Widget::Widget(QWidget *parent)
    :QWidget(parent), m_edit(this)
{
   m_edit.installEventFilter(this);       
}
         //方法一: 重写目标对象的event()函数
bool Widget::event(QEvent* evt)
{
   if( evt->type() == QMouseEvent::MouseButtonDblClick )      
    {
       qDebug() << "event: Before sentEvent";
 
       StringEvent e("Morning ");     
 
       QCoreApplication::sendEvent(&m_edit, &e);         //发送事件对象
 
       qDebug() << "event: After sentEvent";
    }
 
   return QWidget::event(evt);                     
}
         //方法二:通过事件过滤器  
bool Widget::eventFilter(QObject* obj,QEvent* evt)    
{
   if( (obj == &m_edit) && (evt->type() ==StringEvent::TYPE) )
    {
       StringEvent* se = dynamic_cast(evt);
 
       qDebug() << "Receive: " << se->data();
 
        m_edit.insert(se->data());               
 
       return true;                       
    }
 
   return QWidget::eventFilter(obj, evt);   
}
 
Widget::~Widget()
{
   
}


 声明:
此文根据 狄泰学院唐老师的《QT实验分析教程》创作

你可能感兴趣的:(Qt)