初学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中的代码:

  1. #include <QtGui/QApplication>
  2. #include <QCoreApplication>
  3. #include <QEvent>
  4. #include <QObject>
  5. #include <QDebug>
  6. static const QEvent::Type MyEventType = (QEvent::Type)QEvent::registerEventType(QEvent::User+100);
  7. //长官
  8. class MyEvent: public QEvent
  9. {
  10. public:
  11. MyEvent(Type MyEventType):QEvent(MyEventType){}
  12. };
  13. //信使
  14. class MySender: public QCoreApplication
  15. {
  16. public:
  17. MySender(int argc,char *argv[]):QCoreApplication(argc,argv){}
  18. public:
  19. bool notify(QObject *receiver, QEvent *event);
  20. };
  21. bool MySender::notify(QObject *receiver, QEvent *event)
  22. {
  23. if(event->type() == MyEventType)
  24. {
  25. qDebug()<<"MyEventType is coming!";
  26. //return true;
  27. /*这里不能return true,因为重写notify就是在事件被向下传递之前截住它,
  28. 随便搞它,搞完了还得给QCoreApplication::notify向下传递,除非在mySender.notify
  29. 实现了事件向下传递的那一套。直接返回的话myArmy就收不到这个事件,因为执行完这个
  30. mySender.notify的return true后,事件传递被人为的在半截终止了
  31. (见Qt事件处理的五个层次http://blog.csdn.net/michealtx/article/details/6865891 )
  32. ,下面的myArmy的安装的过滤器和它自己的event都不会收到这个事件,更甭提最后干活
  33. 的myEventHandler了。所以在主函数中执行完mySender.sendEvent把myEvent
  34. 交给mySender.notify这个败家子儿后,就执行mySender.exec进入其它事件的循环了。这就是
  35. 问题http://topic.csdn.net/u/20111012/19/78036d16-c163-40f9-a05c-3b7d6f4e9043.html
  36. 出现的原因。感谢1+1=2大牛!非常感谢!
  37. */
  38. }
  39. return QCoreApplication::notify(receiver,event);
  40. }
  41. //军队
  42. class MyArmy: public QObject
  43. {
  44. public:
  45. void MyEventHandler(QEvent *event);
  46. bool event(QEvent *event);
  47. };
  48. void MyArmy::MyEventHandler(QEvent *event)
  49. {
  50. qDebug()<<"The event is being handled!";
  51. event->accept();
  52. }
  53. bool MyArmy::event(QEvent *event)
  54. {
  55. if(event->type() == MyEventType)
  56. {
  57. qDebug()<<"event() is dispathing MyEvent";
  58. MyEventHandler(event);//调用事件处理函数
  59. if((MyEvent*)event->isAccepted())
  60. {
  61. qDebug()<<"The event has been handled!";
  62. return true;
  63. }
  64. }
  65. return QObject::event(event);
  66. }
  67. //监控者
  68. class MyWatcher: public QObject
  69. {
  70. public:
  71. bool eventFilter(QObject *watched, QEvent *event);
  72. };
  73. bool MyWatcher::eventFilter(QObject *watched, QEvent *event)
  74. {
  75. if(event->type() == MyEventType)
  76. {
  77. qDebug()<<"I don't wanna filter MyEventType";
  78. return false;
  79. }
  80. return QObject::eventFilter(watched,event);
  81. }
  82. int main(int argc, char *argv[])
  83. {
  84. //QCoreApplication a(argc, argv);
  85. MySender mySender(argc,argv);
  86. MyArmy myArmy;
  87. MyWatcher myWatcher;
  88. myArmy.installEventFilter(&myWatcher);//安装事件过滤器
  89. MyEvent myEvent(MyEventType);
  90. mySender.sendEvent(&myArmy,&myEvent);
  91. return mySender.exec();
  92. }

运行结果:

好了,就这样了!可能有错误或不准确的地方!望路过的大牛指点!叩谢!ORZ

参考:http://blog.csdn.net/michealtx/article/details/6866094

Qt自定义事件的实现(军队真正干活,但要增加监军,大平台通知事件,事件内容自定义)的更多相关文章

  1. ListView使用自定义适配器的情况下实现适配器的文本和图标控件点击事件执行Activity界面中的方法

    ListView使用的是自定义适配器,列表项的布局文件中含有文本和图标,实现文本区域和图标区域的点击事件. 实现思路:在自定义适配器MyArrayAdapter 类型中自定义接口和接口方法,分别设置文 ...

  2. nopCommerce 3.9 大波浪系列 之 事件机制(生产者、消费者)

    一.nop事件机制简介 应用场景:客户支付成功后,需要发送短信.邮件告知客户订单支付成功(短信.邮件由不同模块实现) 实现方法: 1.定义支付成功OrderPaidEvent事件. 2.定义短信,邮箱 ...

  3. 如何使用 K8s 两大利器"审计"和"事件"帮你摆脱运维困境?

    概述 下面几个问题,相信广大 K8s 用户在日常集群运维中都曾经遇到过: 集群中的某个应用被删除了,谁干的? Apiserver 的负载突然变高,大量访问失败,集群中到底发生了什么? 集群节点 Not ...

  4. IE attachEvent事件处理程序(事件绑定的函数)的this指向的是window不是执行当前事件的dom元素

    IE attachEvent事件处理程序(事件绑定的函数)的this指向的是window不是执行当前事件的dom元素. attachEvent(type,listener); listener函数中的 ...

  5. 通过js或jq增加的代码,点击事件或其他一些事件不起作用时

    通过js或jq增加的代码,点击事件或其他一些事件不起作用时,可使用 $(document).on("click",".noshow",function() { ...

  6. WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件

    在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件.例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开.在这个过程中,控 ...

  7. vue2.0实现一个模态弹框,内容自定义(使用slot)

    定义模态框:合理使用插槽 model.vue <!-- 模态弹窗 --> <template> <div class="self-modal" v-s ...

  8. 关于chrome浏览器事件拖动的bug(首次点击的时候也触发move的事件)

    在做R80web的时候出现一个奇怪的现象,chorme现在的版本还是存在,拖动事件有mousedown.mousemove.mouseup组成,但是首次click以及失去焦点再重新点击的时候同样会触发 ...

  9. JavaScript 兼容各大浏览器阻止冒泡事件

    JavaScript 兼容各大浏览器阻止冒泡事件 function stopEvent(event) { //阻止冒泡事件 //取消事件冒泡 var e = arguments.callee.call ...

随机推荐

  1. 使用Xcode8的Instruments检测解决iOS内存泄露(leak)

    在苹果没有出ARC(自动内存管理机制)时,我们几乎有一半的开发时间都耗费在这么管理内存上.后来苹果很人性的出了ARC,虽然在很大程度上,帮助我们开发者节省了精力和时间.但是我们在开发过程中,由于种种原 ...

  2. Java读书笔记二(封装类)

    1.介绍 都知道java中基本数据类型有非常多,比方string,int--,可是基本数据类型与对象之间是不同的.但非常多情况下,我们希望将基本数据类型当作对象使用,这时候就须要用到封装类. 2.封装 ...

  3. Linux基本配置和管理 2 ---- Linux多命令协作----管道及重定向

    1 管道和重定向 1 在Linux中大多数命令都很简单,很少出现复杂的命令,每个命令只是实现一个简单的功能,我们可以通过组合不同的命令来实现复杂的功能 2 在Linux中几乎所有的命令返回的数据都是纯 ...

  4. Redis配置文件分析

    #Redis演示示例配置文件 # 注意单位问题:当须要设置内存大小的时候,能够使用类似1k.5GB.4M这种常见格式: # # 1k=> 1000 bytes #1kb => 1024 b ...

  5. Html----常见标签

    文本格式化标签 标签 描述 <b> 定义粗体文本. <big> 定义大号字. <em> 定义着重文字. <i> 定义斜体字. <small> ...

  6. 关于 yii 验证码显示, 但点击不能刷新的处理

    先说说 render 与 renderPartial, 各位看官, 先别走, 我没跑题, 这个问题如果需要解决, 关键就在 render 与 renderPartial 的区别. renderPart ...

  7. Android Camera 使用一例,视频聊天app

    视频聊天的应用可以从下面的框图示意.  所以需要从camera获取视频数据(YUV420sp),压缩成H264/MPEG4/H263的包,再传递到对方.接收对方的压缩包,解压出来显示到LCD上. An ...

  8. JS正则表达式验证账号、手机号、电话、邮箱、货币

    验证帐号是否合法验证规则:字母.数字.下划线组成,字母开头,4-16位. function checkUser(str){ var re = /^[a-zA-z]\w{3,15}$/; if(re.t ...

  9. java 类处理工具

    public class ClassUtils { private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtils.cl ...

  10. 初识html、css时随笔记录

    css部分样式 圆框效果:border-radius:5px; 固定样式:position:fixed;悬浮窗在IE6中position:absolute其余浏览器可以用fixed: 使table中的 ...