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. Python 深度递归

    class A: pass class B(A): pass class C(A): pass class D(B, C): pass class E: pass class F(D, E): pas ...

  2. python pygame实现简单的网游

    此示例为简单的实现游戏服务器端和客户端的消息同步,使用自定定义协议,引入了twisted网络框架,还有诸多不足(其实就是半成品). 资源下载地址: http://download.csdn.net/d ...

  3. 反转链表(python3)

    问题描述: 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL解法1: ...

  4. MySQL笔记(1)

    数据库和 SQL 概念 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它的产生距今已有六十多年.随着信息技术和市场的发展,数据库变得无处不在:它在电子商务.银行系统 等众多领域 ...

  5. 大数据-02-Scala入门

    Scala 简介 它是一门基于JVM的面向函数和面向对象的编程语言, 它包含了求值表达式,闭包,切片操作,模式匹配,隐式转换等特性. 可变量/不可变量 可变集合/不可变集合.集合操作 函数 值函数 求 ...

  6. [LeetCode&Python] Problem 349. Intersection of Two Arrays

    Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1 ...

  7. Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)

    (本套题算是比较温和吧,就是罚时有点高. B .Baby Bites 题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组. 思路:从左往右依次固定,看是 ...

  8. js中将一个字一个字的打印出来

    第一种方式: setTimeout(function(){ var cc=document.createTextNode(ss[i]) content.appendChild(cc) },3000)

  9. 《DSP using MATLAB》Problem 6.9

    9月9日,我们怀念毛主席! 代码: %% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...

  10. oracle命令导入SQL脚本

    使用@导入 比如说我在oracle家目录下有a.sql文件 命令行sqlplus / as sysdba,进入后 SQL>@/home/oracle/a.sql; 回车搞定