1、图形界面应用程序的消息处理模型
特点:
  • 基于操作系统才能运行
  • GUI应用程序提供的功能必须由用户触发
  • 用户操作界面时操作系统是第一个感知的
  • 系统内核的消息通过事件处理转变成QT的信
2. Qt中的事件处理
(1)在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent.    
         事件处理的核心包括事件①产生、②分发、③接受和处理
事件的产生

谁来产生事件? 最容易想到的是我们的输入设备,比如键盘、鼠标产生的keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent事件(他们被封装成QMouseEvent和QKeyEvent)。

②Qt中事件的分发

谁来负责分发事件?对于non-GUI的Qt程序,是由QCoreApplication负责将QEvent分发给QObject的子类-Receiver. 
对于Qt GUI程序,由QApplication来负责
 
③事件的接受和处理
谁来接受和处理事件?答案是QObject。
类是整个Qt对象模型的心脏,事件处理机制是QObject三大职责(内存管理、内省(intropection)与事件处理制)之一。任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
(2)Qt平台将系统产生的消息转变成Qt事件
  • Qt事件是一个QEvent(或子类)对象
  • 有时一个事件包含多个事件类型,比如鼠标事件又可以分为鼠标按下双击、和移动多种操作
  • 事件类型由QEvent类的枚举型QEvent::Type来表示,可由帮助文档进行查询
  • Qt事件用于描述程序内部或外部发生的对应动作描述的是操作系统发生来的消息,一个系统消息对应着一个消息事件
  • 任意QObject对象都具备时间处理的能力

QEvent及其子类对象

note:QEvent子类可以表示一个事件,但并不能处理这个事件

Qt 程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将创建一个事件对象。Qt 中所有事件类都继承于QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。如上所述,event()函数主要用于事件的分发。

(3)GUI应用程序的事件处理方式
  • Qt事件产生后会立即被分发到QWidget对象(QObject的子类,如按键QPushButton对象等)
  • QWidget对象其内部会有一个event(QEVent*)函数被调用,进行事件处理
  • event()根据事件类型调用不同的事件处理函数(默认的子函数)
  • 在事件处理函数中发送Qt中预定义的信号
  • 调用信号关联的槽函数

(4) QPushButton事件处理分析

①接收到鼠标事件

②QApplication调用QObject::event(QEvent*)成员函数来处理,进行事件的分派。

③调用QPushButton的mouseReleaseEvent(QMouseEvent*)成员函数

④QPushButton调用click()成员函数

⑤触发信号SIGNAL(clicked())

(5)实例

实例一:自定义事件处理函数

鼠标左键右键

wigth.h

 #ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
Q_OBJECT
protected:
void mousePressEvent(QMouseEvent *event);
public:
Widget(QWidget *parent = );

~Widget();
};

#endif // WIDGET_H

widgth.cpp

 #include "widget.h"
#include <QMouseEvent>
#include <QDebug>
#include <QMenu>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
}

void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
qDebug()<<"LeftButton clicked!";
}
else if(event->button()==Qt::RightButton)
{
qDebug()<<"RightButton clicked!"; }

}

Widget::~Widget()
{ }

main.cpp

 #include <QApplication>
#include "widget.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show(); return a.exec();
}
 实例二:自定义事件处理函数
 
 
QMyPushButton.h

 #ifndef _QMYPUSHBUTTON_H_
#define _QMYPUSHBUTTON_H_ #include <QPushButton> typedef void (QButtonListener)(QObject*,QMouseEvent*); class QMyPushButton : public QPushButton
{
Q_OBJECT protected:
QButtonListener* m_listener; //重写QPushButton的事件处理函数 就有可能不会产生clicked信号
void mouseReleaseEvent(QMouseEvent *e);
public:
explicit QMyPushButton(QWidget* parent = , QButtonListener* listener = );
}; #endif // _QMYPUSHBUTTON_H_

//QMyPushButton.cpp

 #include "QMyPushButton.h"
#include <QMouseEvent> QMyPushButton::QMyPushButton(QWidget* parent, QButtonListener* listener):QPushButton(parent)
{
m_listener = listener;
} //重写改写事件处理函数,会改变程序的行为。
void QMyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
if(m_listener != NULL)
{
//调用自定义的事件处理函数,尽管按钮的clicked信号被连接到onMyButtonClicked槽函数,
//但因自定义的m_listener函数里并不触发clicked信号,从而槽函数不会被调用。
m_listener(this, e);
e->accept();//事件被接收,就不再传递到父QWidget setDown(false); //按钮设置为“弹起”状态
}
else
{
//父类的mouseReleaseEvent会去调用clicked(),并触发SIGNAL(clicked())
//从而调用到连接到该信号的槽函数(本例为onMyButtonClicked())
QPushButton::mouseReleaseEvent(e); //调用父类
}
}

Widget.h

 #ifndef _WIDGET_H_
#define _WIDGET_H_ #include <QWidget>
#include "QMyPushButton.h" class Widget : public QWidget
{
Q_OBJECT
QMyPushButton myButton; protected slots:
void onMyButtonClicked(); public:
Widget(QWidget *parent = );
~Widget();
}; #endif // _WIDGET_H_

Widget.cpp

 #include "Widget.h"
#include <qDebug> //自定义事件处理函数
void onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)
{
qDebug() << "onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)";
} Widget::Widget(QWidget *parent)
: QWidget(parent),myButton(this, onMyButtonMouseRelease) //实验2:myButton(this, 0)
{
myButton.setText("QMyPushButton"); connect(&myButton, SIGNAL(clicked()), this, SLOT(onMyButtonClicked()));
} //槽函数,用于接收按钮的clicked信号
void Widget::onMyButtonClicked()
{
qDebug() << "onMyButtonClicked()" ;
} Widget::~Widget()
{
}

main.cpp

#include "Widget.h"
#include <QApplication> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show(); return a.exec();
}

(4)事件(QEvent)和信号(SIGNAL)的不同

事件(QEvent)

信号(SIGNAL)

与QObject的关系

由具体对象进行处理

由具体对象主动产生

对程序影响

改写事件处理函数可能导致程序行为发生改变

信号是否存在对应的槽函数不会改变程序行为

两者的联系

一般而言,信号在具体的事件处理函数中产生

例如:单击界面上的按钮,那么就会产生鼠标事件QMouseEvent(不是按钮产生的),由于按钮被按下了,所以他会发出一个单击信号clicked()信号(是按钮产生的),这里只考虑单击信号而不用考虑鼠标事件,但如果要设计一个按钮,或者当单击按钮时让它产生别的效果,此时就要考虑鼠标事件了,由此,信号和事件是两个不同层面的东西,发出者不同,作用不同。Qt中,所有的QObject的子类实例均可对事件接收和处理!

3. 小结

(1)Qt中的事件和信号不同

(2)事件由QObject对象进行处理

(3)信号由QObject对象触发

(4)重写事件处理函数可能改变程序行为

(5)信号的触发不会对程序行为造成影响

(6)事件处理是在实际工程开发中应用非常普遍的

Qt 中的事件处理(一)的更多相关文章

  1. 第38课 Qt中的事件处理(上)

    1. GUI程序原理回顾 (1)图形界面应用程序的消息处理模型 (2)思考:操作系统发送的消息如何转变为Qt信号 2. Qt中的事件处理 (1)Qt平台将系统产生的消息转换为Qt事件 ①Qt事件是一个 ...

  2. 第39课 Qt中的事件处理(下)

    1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...

  3. Qt 中的事件处理(二)

    1. 回顾事件传递的过程 ①源头:操作系统   操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中, ②应用程序收到系统消息后, 他会将系统消息翻译成对应的 ...

  4. Qt事件系统之一:Qt中的事件处理与传递

    一.简介 在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的 ...

  5. QT_8_Qt中的事件处理_定时器事件_定时器类_事件分发器_事件过滤器_绘图事件_高级绘图事件_绘图设备_QFile 文件读写_QFileInfo文件信息

    Qt中的事件处理 1.1. 捕获QLabel中是鼠标事件 1.2. enterevent 鼠标进入 1.3. leaveevent 鼠标离开 1.4. 鼠标按下MyLabel::mousePressE ...

  6. Qt中事件处理的方法(三种处理方法,四种覆盖event函数,notify函数,event过滤,事件处理器。然后继续传递给父窗口。可观察QWidget::event的源码,它是虚拟保护函数,可改写)

    一.Qt中事件处理的方式   1.事件处理模式一 首先是事件源产生事件,最后是事件处理器对这些事件进行处理.然而也许大家会问, Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是 ...

  7. Qt中事件处理的顺序

    本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息.原文链接.原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途. 谢谢合作.原文链接:Qt中事件处理的顺序 文章内容主要来自 ...

  8. Qt中的事件

    1. 引自---http://blog.sina.com.cn/s/blog_6e80f1390100pro4.html 信号和事件的区别就在与,事件比信号更加底层,而且如果一个信号对应多个槽的话,信 ...

  9. Qt中的键盘事件,以及焦点的设置(比较详细)

    Qt键盘事件属于Qt事件系统,所以事件系统中所有规则对按键事件都有效.下面关注点在按键特有的部分: focus 一个拥有焦点(focus)的QWidget才可以接受键盘事件.有输入焦点的窗口是活动窗口 ...

随机推荐

  1. vue国际化插件

    1.安装 $ npm install vue-i18n 2.引入 import VueI18n from 'vue-i18n' Vue.use(VueI18n) const i18n = new Vu ...

  2. POJ 3461 Oulipo(KMP裸题)

    Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without t ...

  3. REST是什么?

    REST -- REpresentational State Transfer 直接翻译:表现层状态转移.   @Ivony 老师的一句话概括很精辟: 用URL定位资源,用HTTP动词(GET,POS ...

  4. 如何使用DAX函数解决动态图表标题

    您可能知道,Power BI中的图表(以及许多其他可视化)具有可以设置为任何静态文本的标题.您可以通过选择图表,转到“可视化对象”窗格中的“格式”选项卡,然后更改“标题”部分中的属性(如下所示)来完成 ...

  5. [转]springcloud(九):配置中心和消息总线(配置中心终结版)

    https://www.cnblogs.com/ityouknow/p/6931958.html springcloud(九):配置中心和消息总线(配置中心终结版) 我们在springcloud(七) ...

  6. Spring架构-01-微服务架构

    一.单体架构 所有功能,所有模块都耦合在一个系统里面,如传统的一MVC. 需要重新编译测试,重新部署. 伸缩性差 可靠性差 系统迭代困难 跨开发语言程序低 团队协作麻烦 二.微服务架构 常见架构风格: ...

  7. Python中random模块在主函数中设置随机种子是否对于调用的函数中的随机值产生影响?

    一个问题,加入我有一个工程文件,在main函数里面调用random模块,设置随机种子,主函数中的随机种子的设置是否会影响主函数所调用的函数中的随机值? 实际上这个问题非常重要,比如你在跑网络的时候,初 ...

  8. Nginx配置之location模块和proxy模块

    1.location指令的用法介绍 Location主要用来匹配url,如:http://www.beyond.com/nice,在这里对于location来说www.beyond.com是域名,/n ...

  9. c标签取数组中的对象值的2种方法

    1:循环遍历 <c:forEach items="${partsDeltailsList}" var="var" varStatus="vs&q ...

  10. 《DSP using MATLAB》Problem 5.28

    昨晚手机在看X信的时候突然黑屏,开机重启都没反应,今天维修师傅说使用时间太长了,还是买个新的吧,心疼银子啊! 这里只放前两个小题的图. 代码: 1. %% ++++++++++++++++++++++ ...