Qt 中的事件处理(二)
(1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序
(2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject::event()将其分发出去。
(3)事件对应被分发到当前正在操作的窗口部件上,该窗口部件会调用QWidget::event()函数来处理,然后,在这个函数内部又会调用其他的子函数(如KeyPressEvent或mouseReleaseEvent)来进行具体的处理。
(4)event函数处理完后,可能会将当前事件传递给父组件(parent)对象。但这个过程只是一种可能,也就是有一部分会被传递,有些并不需要被传递。
2. QEvent及其子类对象涉及的关键成员函数:实际上只是在操作或判断一个标志位
(1)void ignore():事件的接收者忽略当前事件,事件可能传递给父组件
(2)void accept();事件的接收者期望处理当前事件,表明我们自己写了事件处理函数,一般不需要被父组件再处理
(3)bool isAccepted();判断当前事件是否被处理
void MyLineEdit::keyPressEvent(QKeyEvent *e)
{
qDebug()<<"MyLineEdit::keyPressEvent";
QLineEdit::keyPressEvent(e);// 执行QLineEdit类的默认事件处理
}
实例事件处理的顺序
//main.cpp
#include "Widget.h"
#include <QApplication> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show(); return a.exec();
}
/*当在编辑框中按下按键时输出结果:(注意MyLineEdit的父组件,即w中的
的event事件并未被触发
MyLineEdit::event
MyLineEdit::keyPressEvent
*/
//MyLineEdit.h
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H #include <QLineEdit> class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit MyLineEdit(QWidget* parent = );
bool event(QEvent* e);
void keyPressEvent(QKeyEvent* e);
}; #endif // MYLINEEDIT_H
//MyLineEdit.cpp
#include "MyLineEdit.h"
#include <QKeyEvent>
#include <QDebug> MyLineEdit::MyLineEdit(QWidget* parent):QLineEdit(parent)
{ } bool MyLineEdit::event(QEvent* e)
{
if( e->type() == QEvent::KeyPress)
{
qDebug() << "MyLineEdit::event";
}
return QLineEdit::event(e);
} void MyLineEdit::keyPressEvent(QKeyEvent* e)
{
qDebug() << "MyLineEdit::keyPressEvent";
QLineEdit::keyPressEvent(e); // e->ignore(); //表示事件会继续传递给父组件,本例中为Widget对象
//如果注释或e-accept()表示不再传递,则父组件的
//event函数不会被触发
}
//Widget.h
#ifndef WIDGET_H
#define WIDGET_H #include <QWidget>
#include "MyLineEdit.h" class Widget : public QWidget
{
Q_OBJECT private:
MyLineEdit myLineEdit; public:
Widget(QWidget *parent = ); bool event(QEvent* e);
void keyPressEvent(QKeyEvent* e); ~Widget();
}; #endif // WIDGET_H
//Widget.cpp
#include "Widget.h"
#include <QEvent>
#include <QDebug> Widget::Widget(QWidget *parent)
: QWidget(parent),myLineEdit(this)
{
} //操作系统将消息转化为事件,并分发到了这个Widget,会首先调用
//这个Wiget的event函数,该函数可以收到多种的系统事件,同时其内部会根据event
//事件的类型调用相应的事件处理函数,如keyPressEvent()。比如,当发生按键事件时
//会先调用event(),再调用后面的keyPressEvent()
bool Widget::event(QEvent* e)
{
if(e->type() == QEvent::KeyPress)
{
qDebug() << "Widget::event";
} return QWidget::event(e);
} void Widget::keyPressEvent(QKeyEvent *e)
{
qDebug() << "Widget::keyPressEvent";
QWidget::keyPressEvent(e);
} Widget::~Widget()
{ }
3. Qt中的事件过滤器
(1)事件过滤器
①事件过滤器可以对其他组件接收到的事件进行监控
②任意的QObject对象都可以作为事件过滤器使用。
③事件过滤器对象需要重写eventFilter()函数。
(2)安装事件过滤器:installEventFilter()函数
①事件过滤器在组件之前接收到事件
②事件过滤器能够决定是否将事件转到到组件对象
(3)Qt中的事件过滤器与dll中的勾子的不同
①Qt中事件的过滤,是由事件的目标对象自己,发起过滤请求的。即委托过滤器,在自己接收事件前,先叫过滤器过滤一下。这意味着目标对象是知道这个过滤器的存在的。如下面例子中的myLineEdit.installEventFilter(this),就是myLineEdit委托Widget对事件进行过滤。
②而dll中的勾子不管目标对象愿不愿意,消息都会被拦下,而且目标对象本身也并不知道勾子的存在。
(4)事件过滤器的典型实现
//场景:将所有发往obj的事件先经过指定的过滤函数处理一下,然后再发往obj
//返回true表示事件己经处理,无需再传递给obj对象了
//返回false则正常传递到obj对象
bool Widget::eventFilter(QObject* obj, QEvent* e)
{
if(/*根据obj判断是否是所需的目标对象*/)
{
if(/*根据e->type()判断是否是感兴趣的事件*/)
{
/*事件处理逻辑*/
}
} /*调用父类中的同名函数*/
return QWidget::eventFilter(obj, e);
}
main.cpp
#include <QApplication>
#include "widget.h" int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show(); return a.exec();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H #include <QWidget>
#include "mylineedit.h" class Widget : public QWidget
{
Q_OBJECT
MyLineEdit* lineEdit;
protected:
void keyPressEvent(QKeyEvent *);
public:
Widget(QWidget *parent = 0);
~Widget();
bool eventFilter(QObject* obj, QEvent *event);
}; #endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
lineEdit=new MyLineEdit(this);
//安装事件过滤器,即让所有发往myLineEdit的事件先由经由eventFilter过滤,这里委派Widget的EventFilter来过滤
lineEdit->installEventFilter(this);//在Widget上为lineedit安装事件过滤器了
} Widget::~Widget()
{ } bool Widget::eventFilter(QObject *obj, QEvent *event)//事件过滤器
{
//该过滤器只过滤发往myLineEdit对象的KeyPress事件
if(obj==lineEdit)//判断事件的对象是不是linEdit
{
if(event->type()==QEvent::KeyPress)//判断事件类型
{
qDebug()<<"Widget::eventFilter";
}
}
return QWidget::eventFilter(obj, event);//最后返回QWidget类默认的事件过滤器的执行结果
} void Widget::keyPressEvent(QKeyEvent *)
{
qDebug()<<"Widget::keyPressEvent";
}
mylinedit.h
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H #include <QLineEdit>
#include <QEvent>
class MyLineEdit : public QLineEdit
{
Q_OBJECT
protected:
void keyPressEvent(QKeyEvent *e); public:
explicit MyLineEdit(QWidget *parent = 0); bool event(QEvent* event);
signals: public slots: }; #endif // MYLINEEDIT_H
mylineedit.cpp
#include "mylineedit.h"
#include <QDebug>
#include <QkeyEvent>
#include <QLineEdit>
MyLineEdit::MyLineEdit(QWidget *parent) :
QLineEdit(parent)
{ } bool MyLineEdit::event(QEvent *event)
{
if(event->type()==QEvent::KeyPress)
qDebug()<<"MyLineEdit::event"; return QLineEdit::event(event);//执行QLineEdit类的event()函数的默认操作 因为event()函数是有一个bool型返回值所以在函数的最后要使用return语句,这里一般是返回父类的event()函数的操作结果
} void MyLineEdit::keyPressEvent(QKeyEvent *e)
{
qDebug()<<"MyLineEdit::keyPressEvent"; // QLineEdit::keyPressEvent(e);
e->ignore();
}
当点击键盘按键时,执行结果为:
Widget::eventFilter
MyLineEdit::event
MyLineEdit::keyPressEvent
Widget::keyPressEvent
可以看到事件的传递顺序是:事件过滤器----->该部件的event()函数------>该部件的事件处理函数------>有可能是父组件的event函数(如果子部件ignore())
3. 小结
(1)Qt应用程序有严格的事件处理顺序
(2)Qt事件在处理后可能传递给父组件对象
(3)可以通过installEventFilter()函数安装事件过滤器
(4)事件过滤器可以对其他组件接收到的事件进行监控
(5)事件过滤器能够决定是否将事件转发到组件对象
Qt 中的事件处理(二)的更多相关文章
- Qt 中的事件处理(一)
1.图形界面应用程序的消息处理模型 特点: 基于操作系统才能运行 GUI应用程序提供的功能必须由用户触发 用户操作界面时操作系统是第一个感知的 系统内核的消息通过事件处理转变成QT的信号 2. Qt中 ...
- 第38课 Qt中的事件处理(上)
1. GUI程序原理回顾 (1)图形界面应用程序的消息处理模型 (2)思考:操作系统发送的消息如何转变为Qt信号 2. Qt中的事件处理 (1)Qt平台将系统产生的消息转换为Qt事件 ①Qt事件是一个 ...
- Qt事件系统之一:Qt中的事件处理与传递
一.简介 在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的 ...
- 第39课 Qt中的事件处理(下)
1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...
- OS开发中的事件处理(二)-事件传递,响应者链条
事件处理的事件传递 简介: 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件 队列中,UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理, ...
- QT_8_Qt中的事件处理_定时器事件_定时器类_事件分发器_事件过滤器_绘图事件_高级绘图事件_绘图设备_QFile 文件读写_QFileInfo文件信息
Qt中的事件处理 1.1. 捕获QLabel中是鼠标事件 1.2. enterevent 鼠标进入 1.3. leaveevent 鼠标离开 1.4. 鼠标按下MyLabel::mousePressE ...
- Qt中事件处理的方法(三种处理方法,四种覆盖event函数,notify函数,event过滤,事件处理器。然后继续传递给父窗口。可观察QWidget::event的源码,它是虚拟保护函数,可改写)
一.Qt中事件处理的方式 1.事件处理模式一 首先是事件源产生事件,最后是事件处理器对这些事件进行处理.然而也许大家会问, Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是 ...
- QT开发(十二)——QT事件处理机制
一.QT事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下和松开 ...
- Qt中事件处理的顺序
本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息.原文链接.原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途. 谢谢合作.原文链接:Qt中事件处理的顺序 文章内容主要来自 ...
随机推荐
- Example of Abstract Class
The Vehicle class has abstract members that must be implemented by the Car class or any other class ...
- Python 静态方法
class Person: @staticmethod # 静态方法 def yue(): print("fsadf") # 静态方法可以使用对象访问. 也可以使用类名访问. 但是 ...
- HDU 6143 17多校8 Killer Names(组合数学)
题目传送:Killer Names Problem Description > Galen Marek, codenamed Starkiller, was a male Human appre ...
- Power BI与Tableau基于Google搜索上的比较
在数据分析领域里,不少的数据爱好者都会关心什么数据分析产品最好用?最重要的是,很多的企业也特别希望员工能真正知道如何使用这些BI平台以确保公司的投资是值得.同类的文章,小悦也曾发布过,可参考最近< ...
- js--call( )/apply()/bind()--应用
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call funct ...
- IK 中文分词器
链接:https://github.com/wks/ik-analyzerIKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始,IKAna ...
- unity中实现简单对象池,附教程原理
Unity对象池的创建与使用 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)
(本套题算是比较温和吧,就是罚时有点高. B .Baby Bites 题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组. 思路:从左往右依次固定,看是 ...
- 测试那些事儿—web测试方法之输入框
一.字符型输入 (1)字符型输入框 英文全角,英文半角,数字,空或者空格,特殊字符“~!@#¥%.......&*?{}[]"特别要注意单引号和&符号.禁止直接输入特殊字符时 ...
- fold算法(拉格朗日插值)
如果打表发现某个数列: 差分有限次之后全为0 例如: 2017新疆乌鲁木齐ICPC现场赛D题 ,,,,,,,,,,…… [2018江苏南京ICPC现场赛也有这样的题目] 那么可以使用以下黑科技计算出第 ...