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来影响送信过程。
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中的代码:
- #include <QtGui/QApplication>
- #include <QCoreApplication>
- #include <QEvent>
- #include <QObject>
- #include <QDebug>
- static const QEvent::Type MyEventType = (QEvent::Type)QEvent::registerEventType(QEvent::User+100);
- //长官
- class MyEvent: public QEvent
- {
- public:
- MyEvent(Type MyEventType):QEvent(MyEventType){}
- };
- //信使
- class MySender: public QCoreApplication
- {
- public:
- MySender(int argc,char *argv[]):QCoreApplication(argc,argv){}
- public:
- bool notify(QObject *receiver, QEvent *event);
- };
- bool MySender::notify(QObject *receiver, QEvent *event)
- {
- if(event->type() == MyEventType)
- {
- qDebug()<<"MyEventType is coming!";
- //return true;
- /*这里不能return true,因为重写notify就是在事件被向下传递之前截住它,
- 随便搞它,搞完了还得给QCoreApplication::notify向下传递,除非在mySender.notify
- 实现了事件向下传递的那一套。直接返回的话myArmy就收不到这个事件,因为执行完这个
- mySender.notify的return true后,事件传递被人为的在半截终止了
- (见Qt事件处理的五个层次http://blog.csdn.net/michealtx/article/details/6865891 )
- ,下面的myArmy的安装的过滤器和它自己的event都不会收到这个事件,更甭提最后干活
- 的myEventHandler了。所以在主函数中执行完mySender.sendEvent把myEvent
- 交给mySender.notify这个败家子儿后,就执行mySender.exec进入其它事件的循环了。这就是
- 问题http://topic.csdn.net/u/20111012/19/78036d16-c163-40f9-a05c-3b7d6f4e9043.html
- 出现的原因。感谢1+1=2大牛!非常感谢!
- */
- }
- return QCoreApplication::notify(receiver,event);
- }
- //军队
- class MyArmy: public QObject
- {
- public:
- void MyEventHandler(QEvent *event);
- bool event(QEvent *event);
- };
- void MyArmy::MyEventHandler(QEvent *event)
- {
- qDebug()<<"The event is being handled!";
- event->accept();
- }
- bool MyArmy::event(QEvent *event)
- {
- if(event->type() == MyEventType)
- {
- qDebug()<<"event() is dispathing MyEvent";
- MyEventHandler(event);//调用事件处理函数
- if((MyEvent*)event->isAccepted())
- {
- qDebug()<<"The event has been handled!";
- return true;
- }
- }
- return QObject::event(event);
- }
- //监控者
- class MyWatcher: public QObject
- {
- public:
- bool eventFilter(QObject *watched, QEvent *event);
- };
- bool MyWatcher::eventFilter(QObject *watched, QEvent *event)
- {
- if(event->type() == MyEventType)
- {
- qDebug()<<"I don't wanna filter MyEventType";
- return false;
- }
- return QObject::eventFilter(watched,event);
- }
- int main(int argc, char *argv[])
- {
- //QCoreApplication a(argc, argv);
- MySender mySender(argc,argv);
- MyArmy myArmy;
- MyWatcher myWatcher;
- myArmy.installEventFilter(&myWatcher);//安装事件过滤器
- MyEvent myEvent(MyEventType);
- mySender.sendEvent(&myArmy,&myEvent);
- return mySender.exec();
- }
运行结果:

好了,就这样了!可能有错误或不准确的地方!望路过的大牛指点!叩谢!ORZ
参考:http://blog.csdn.net/michealtx/article/details/6866094
Qt自定义事件的实现(军队真正干活,但要增加监军,大平台通知事件,事件内容自定义)的更多相关文章
- ListView使用自定义适配器的情况下实现适配器的文本和图标控件点击事件执行Activity界面中的方法
ListView使用的是自定义适配器,列表项的布局文件中含有文本和图标,实现文本区域和图标区域的点击事件. 实现思路:在自定义适配器MyArrayAdapter 类型中自定义接口和接口方法,分别设置文 ...
- nopCommerce 3.9 大波浪系列 之 事件机制(生产者、消费者)
一.nop事件机制简介 应用场景:客户支付成功后,需要发送短信.邮件告知客户订单支付成功(短信.邮件由不同模块实现) 实现方法: 1.定义支付成功OrderPaidEvent事件. 2.定义短信,邮箱 ...
- 如何使用 K8s 两大利器"审计"和"事件"帮你摆脱运维困境?
概述 下面几个问题,相信广大 K8s 用户在日常集群运维中都曾经遇到过: 集群中的某个应用被删除了,谁干的? Apiserver 的负载突然变高,大量访问失败,集群中到底发生了什么? 集群节点 Not ...
- IE attachEvent事件处理程序(事件绑定的函数)的this指向的是window不是执行当前事件的dom元素
IE attachEvent事件处理程序(事件绑定的函数)的this指向的是window不是执行当前事件的dom元素. attachEvent(type,listener); listener函数中的 ...
- 通过js或jq增加的代码,点击事件或其他一些事件不起作用时
通过js或jq增加的代码,点击事件或其他一些事件不起作用时,可使用 $(document).on("click",".noshow",function() { ...
- WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件
在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件.例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开.在这个过程中,控 ...
- vue2.0实现一个模态弹框,内容自定义(使用slot)
定义模态框:合理使用插槽 model.vue <!-- 模态弹窗 --> <template> <div class="self-modal" v-s ...
- 关于chrome浏览器事件拖动的bug(首次点击的时候也触发move的事件)
在做R80web的时候出现一个奇怪的现象,chorme现在的版本还是存在,拖动事件有mousedown.mousemove.mouseup组成,但是首次click以及失去焦点再重新点击的时候同样会触发 ...
- JavaScript 兼容各大浏览器阻止冒泡事件
JavaScript 兼容各大浏览器阻止冒泡事件 function stopEvent(event) { //阻止冒泡事件 //取消事件冒泡 var e = arguments.callee.call ...
随机推荐
- Java中的字符串流的读取和写入(创建文件并判断重复账户)
各位我又来了!!哎!好心酸!我还没注册到三天!!没法登上博客的首页!!心累!! import java.io.BufferedOutputStream; import java.io.Buffered ...
- QueryPerformanceFrequency使用方法--Windows高精度定时计数
在多核心或多处理器的计算机上.特别是在支持CPU频率动态调整的计算机上,windows系统下的QueryPerformanceFrequency()获取HPET(假设存在)的频率,而QueryPerf ...
- x64位windows上程序开发的注意事项
在Windows上面32位与64位的区别有: 1.指针大小的区别,sizeof(int *)在32bit下面是4个字节,在64bit下面是8个字节 2.size_t的区别,size_t在32bit下面 ...
- Linux后台开发面试问题汇总
个人从事安全后台开发,当然是linux环境下的了.举几个常见的问题.1. 数据结构基础.比如实现一个最简单的哈希表.2. 操作系统基础.linux进程模型,堆/栈的区别,大概的位置,各往哪个方向生长, ...
- 使用<input>标签做了两个按钮, 按钮之间间距如何去掉
遇到的问题: 使用<input>标签做了两个按钮, 按钮之间有个间距不知道怎么去掉. 如下图: 问题解决: <input>是内联块状元素(inline-block); 内联元素 ...
- MeasureSpec
在自定义View和ViewGroup的时候,我们经常会遇到int型的MeasureSpec来表示一个组件的大小,这个变量里面不仅有组件的尺寸大小,还有大小的模式. 这个大小的模式,有点难以理解.在系统 ...
- System.Management命名空间
提供对大量管理信息和管理事件集合的访问,这些信息和事件是与根据 Windows 管理规范 (WMI) 结构对系统.设备和应用程序设置检测点有关的.应用程序和服务可以使用从 ManagementObje ...
- oracle特殊字符的ascii值
- AutoLayout(转)
转自 http://blog.sina.com.cn/s/blog_9564cb6e0101wv9o.html controller和View的责任分配: 1.View指定固有的content ...
- iOS程序崩溃*** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [37.5 nan]'
今天上班打开昨天的程序运行,昨天跑的很溜的程序今天竟然crash了,好郁闷啊!下面附上crash的栈打印信息: 经过一番调试终于找到了原因,程序crash是因为CALayer的位置中含有不存在的数,就 ...