Qt 自定义事件的实现
初学Qt,用了Qt自带的事件,然后想怎么才能定义自己的事件呢?又如何使用自定义事件呢?看了篇文章,说先要子类化QEvent,然后定义自己的QEvent::Type,然后重写QWidget::event()函数,然后就可以调用QCoreApplication::sendEvent()或者QCoreApplication:;postEvent()发送事件就好了。但我比较笨,还是云山雾罩,不知道怎么下手。
怎么子类化QEvent?在哪里定义自己的QEvent::Type?在哪里重写QWidget::event()函数?在哪里调用QCoreApplication::sendEvent()或者QCoreApplication:;postEvent()发送事件?
在百度里搜索开了篇文章对我有启发http://bluemask.net/p/1215/ ,在google中搜索how to subclass QEvent也搜到一篇对我有启发的http://www.java2s.com/Code/Cpp/Qt/SubclassQEvent.htm 。(google的英文搜索真不错!)
后来我就想,那Qt的发明人是怎么定义事件的呢?其实站在Qt发明人的角度,QEvent就是他们的“自定义事件”!Ok!这就好办了!看看Qt发明人怎么定义的QEvent,看看他们怎么用自己定义的QEvent,不就回答了文章开头的俩问题了嘛!O(∩_∩)O~
我把整个过程总结为“长官定义事件”----->“信使传递事件”---->“军队接收并响应事件”。
我通过Qt Assistant查找那些与事件相关的类,总结如下:
1、Qt中定义事件的长官:QEvent
QEvent的任务就是定义一些事件类型Type,它们都定义在了一个enum里。这就是教程中告诉我们的要子类化QEvent,派生出MyEvent,然后在MyEvent中定义事件类型QEvent::Type。
我们子类化的时候模仿一个QEvent就好了,而且是继承,好些都不用子类做了,看一下QEvent类中的成员变量和成员函数,就这些东西:
好了,我们通过子类化QEvent,把派生出来的MyEvent看做长官,它定义了具体某个事件。下面看谁是信使。
2、Qt中传递事件的信使:QCoreApplication(QApplication继承自QCoreApplication)
我们看看QCoreApplication中定义的一些函数,这些函数就是我们经常遇到的那些与传递事件和过滤事件有关的函数,见下图:
Public Functions:
Static Public Members:
所以,到这里我们就可以明确了,你要用QCoreApplication的static public类型的函数入sendEvent或postEvent函数来传递送信,要注意:当使用sendEvent时,你的事件要在栈上建立,sendEvent会直接调用notify把事件传递给士兵,不走事件队列;而用postEvent时,你的事件要在堆上建立,即要用new来创建,postEvent会把你的事件追加进事件队列(详细过程请看http://blog.csdn.net/michealtx/article/details/6865891)。你还可以通过重载notify来影响送信过程。
注意C++:在函数内下列声明
一种是在栈上创建类对象,形式如下:CSomeClass someObject;
一种是在堆上创建(动态分配),形式如下:CSomeClass *pSomeObject = new CSomeClass();
具体一定要看这一篇文章:https://www.devbean.net/2014/02/cpp-create-object-on-heap-or-stack/ 《C++:在堆上创建对象,还是在栈上?》
3、Qt中接收响应事件的军队:QWidget(这是Qt中的widget之母,诸如QMainWindow、QPushBUtton等等都是继承自QWidget)
我们看看QWidget中与事件有关的成员:
看到了吗?这些就是event handler,即事件处理函数,这是干活的那帮人。里面有我们熟悉的mousePressEvent()、keyPressEvent()等常用的事件处理函数,它们都是protected virtual 类型的,可以重载。所以呀,我们可以子类化QWidget,从而继承得到好些个event handler,当然也可以自己定义event handler!相当于自己创造士兵来响应事件。通过山寨QWidget,就可以创造自己的军队!
还有一点就是,当事件到达军队的时候,要先审查再分发,审查就是要经过事件过滤,分发就是通过对经过审查的事件进行判断再把它分给那个相应的士兵这就又涉及到一个类QObject,这是Qt的万类之母,这个类中有两个函数一个是eventFilter(),另一个是event()。要先子类化QObject来创建一个监控者,这个监控者重载eventFilter(),来为军队过滤事件。然后还要在军队(QWidget)通过调用installEventFilter ( QObject * filterObj )来安装过滤器,参数中的filterOb即为监控者。最后在军队(QWidget)中重载event()来分发事件,把事件分给对应会干这个活的士兵(event handler)。
好了,我理解的大体过程就是这样,我是Qt新手,可能有错的地方,希望路过的大牛能给与指正,我将不胜感激!
什么话也不如来个例程给力!:
我建立的是Qt Console Application,工程叫MyEvent,下面是main.cpp中的代码:
1 #include <QtGui/QApplication> 2 #include <QCoreApplication> 3 #include <QEvent> 4 #include <QObject> 5 #include <QDebug> 6 7 //声明、定义、注册自定义事件类型,事件ID为自定义事件ID起点QEvent::User +100=1100 8 static const QEvent::Type MyEventType = (QEvent::Type)QEvent::registerEventType(QEvent::User+100); 9 10 //长官 11 class MyEvent: public QEvent 12 { 13 public: 14 MyEvent(Type myeventtype):QEvent(myeventtype){} 15 }; 16 17 //信使 18 class MySender: public QCoreApplication 19 { 20 public: 21 MySender(int argc,char *argv[]):QCoreApplication(argc,argv){} 22 23 public: 24 bool notify(QObject *receiver, QEvent *event); 25 26 }; 27 28 bool MySender::notify(QObject *receiver, QEvent *event) 29 { 30 if(event->type() == MyEventType) 31 { 32 qDebug()<<"MyEventType is coming!"; 33 //return true; 34 /*这里不能return true,因为重写notify就是在事件被向下传递之前截住它, 35 随便搞它,搞完了还得给QCoreApplication::notify向下传递,除非在mySender.notify 36 实现了事件向下传递的那一套。直接返回的话myArmy就收不到这个事件,因为执行完这个 37 mySender.notify的return true后,事件传递被人为的在半截终止了 38 (见Qt事件处理的五个层次http://blog.csdn.net/michealtx/article/details/6865891 ) 39 ,下面的myArmy的安装的过滤器和它自己的event都不会收到这个事件,更甭提最后干活 40 的myEventHandler了。所以在主函数中执行完mySender.sendEvent把myEvent 41 交给mySender.notify这个败家子儿后,就执行mySender.exec进入其它事件的循环了。这就是 42 问题http://topic.csdn.net/u/20111012/19/78036d16-c163-40f9-a05c-3b7d6f4e9043.html 43 出现的原因。感谢1+1=2大牛!非常感谢! 44 */ 45 } 46 return QCoreApplication::notify(receiver,event); 47 } 48 49 //军队 50 class MyArmy: public QObject 51 { 52 public: 53 void MyEventHandler(QEvent *event);//自定义事件函数 54 bool event(QEvent *event); 55 }; 56 57 void MyArmy::MyEventHandler(QEvent *event) 58 { 59 qDebug()<<"The event is being handled!"; 60 event->accept(); 61 } 62 63 bool MyArmy::event(QEvent *event) 64 { 65 if(event->type() == MyEventType) 66 { 67 qDebug()<<"event() is dispathing MyEvent"; 68 MyEventHandler(event);//调用事件处理函数 69 if((MyEvent*)event->isAccepted()) 70 { 71 qDebug()<<"The event has been handled!"; 72 return true; 73 } 74 } 75 return QObject::event(event); 76 } 77 78 //监控者 79 class MyWatcher: public QObject 80 { 81 public: 82 bool eventFilter(QObject *watched, QEvent *event); 83 }; 84 85 bool MyWatcher::eventFilter(QObject *watched, QEvent *event) 86 { 87 if(event->type() == MyEventType) 88 { 89 qDebug()<<"I don't wanna filter MyEventType"; 90 return false; 91 } 92 return QObject::eventFilter(watched,event); 93 } 94 95 96 int main(int argc, char *argv[]) 97 { 98 //QCoreApplication a(argc, argv); 99 MySender mySender(argc,argv); 100 101 MyArmy myArmy; 102 MyWatcher myWatcher; 103 myArmy.installEventFilter(&myWatcher);//安装事件过滤器 104 105 MyEvent myEvent(MyEventType); 106 mySender.sendEvent(&myArmy,&myEvent); 107 return mySender.exec(); 108 }
运行结果:
好了,就这样了!可能有错误或不准确的地方!望路过的大牛指点!
转自:http://blog.csdn.net/MichealTX/article/details/6866094
Qt 自定义事件的实现相关推荐
- Qt自定义事件实现及子线程向主线程传送事件消息
近期在又一次学习Qt的时候,由于要涉及到子线程与主线程传递消息,所以便琢磨了一下.顺便把有用的记录下来,方便自己以后查询及各位同仁的參考! 特此声明,本篇博文主要讲述有用的,也就是直接说明怎么实现,就 ...
- 【QT】自定义事件 QCustomEvent
[QT]自定义事件 一.自定义事件的优势 尽管 Qt 已经提供了很多事件,但对于更加千变万化的需求来说,有限的事件都是不够的.例如,我要支持一种新的设备,这个设备提供一种崭新的交互方式,那么,这种事件 ...
- Qt线程间通信-自定义事件
线程间通信: 1.自定义事件:postEvent(): 2.信号与槽[本质也是通过自定义事件实现的] 注意:每个线程都有自己的事件循环 自定义事件: 1.从QEvent继承: 2.registerEv ...
- Qt 自定义信号与槽
注 对象与槽理解 //第一个参数lineEdit是激发事件对象,信号中的方法必须在对象中存在,并在对象类头文件signals下定义,//第二个参数信号,//第三个参数this是槽方法所属类的对象,且必 ...
- QT中事件发送函数sendEvent()、postEvent()详解
Qt发送事件分为两种 -阻塞型事件发送 需要重写接收对象的event()事件处理函数 当事件发送后,将会立即进入event()事件处理函数进行事件处理 通过sendEvent()静态函数实现阻塞发送: ...
- QT的事件分发、事件过滤器详解
一.事件的流向 QT的各种控件(QObject的子类)都有事件处理成员函数,例如: bool QObject::event(QEvent *e);//所有事件 dragEnterEvent(QDrag ...
- Qt中事件循环机制详解
问题1:Qt中常见的事件有哪些? 答:鼠标事件(QMouseEvent).键盘事件(QKeyEvent).绘制事件(QPaintEvent).窗口尺寸改变(QResizeEvent).滚动事件(QSc ...
- Qt 自定义标题栏,最小化、最大化、关闭窗口,双击最大化,鼠标拖动等效果实现
文章目录 前言 效果 代码 .pro文件 widget.h widget.cpp widget.ui title.h title.cpp title.ui 前言 本次实验内容为Qt自定义标题栏,最小化 ...
- QT 自定义分页控件
Qt 自定义页码控件 一.效果展示 二.头文件 #ifndef PAGECONTROL_H #define PAGECONTROL_H #include <QList> #include ...
最新文章
- 使用Keras计算余弦相似度(Cosine Similarity)
- 在qt中用c语言数组,在QT函数中返回一个数组/把一个数组传参给函数
- 创建一个最简单的imgui测试用例
- Android 浮窗开发之窗口层级
- mysql到es的交叉验证
- java求职英文简历范本2篇_JAVA英文求职简历范文
- 3Dmax转cad及批量出图
- Android 分贝测试仪功能,挥泪整理面经
- IIS发布网站 后台接口404
- Windows系统下使用WCP搭建自己的本地知识库管理平台
- 【前端性能优化】图片加载优化
- 自己当笔记写着玩吧--leetcode- 001
- Linux Ubuntu NVIDIA双显卡切换intel显卡方法, 如果无法正常切换
- top命令的原理是什么
- 做一只跑过灰狼的兔子
- 计算Dataframe指定位置上的分位数:df.quantile()
- MTK5G模块芯片MTK6873_MT6873数据手册/datasheet/规格书
- 自建latex服务器,快速部署支持 Makedown 和 LaTeX 等格式的 Zbox-Wiki 文档共享站点
- SSIS 錯誤碼 DTS_E_OLEDBERROR。發生 OLE DB 錯誤。錯誤碼: 0x80040E21 备注
- Cisco Packet Tracer入门--三层交换机局域网搭建+DHCP配置教程
热门文章
- Linux软件安装的几种方法 (三)—— 源码安装
- 7-192 素因子分解 (20 分)
- 回文判断(栈+队列)
- HTTP响应头信息 Content-Disposition 文件的显示或下载
- jquery.js和jquery-1.4.2.min.js的区别
- oracle clusterware 11g,Oracle11gR2clusterware启动顺序
- ie提示保护计算机关闭网页,xp系统解决IE为保护计算机关闭网页方法分享
- 学php记不住函数,为什么都是记不住PHP 的函数名
- 栈方法 LIFO - 队方法 FIFO
- mangTomany 自关联之个人感悟