1         QT事件系统

1.1  事件的定义

QT中事件是有专门的类QEvent,常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent。例如用鼠标单击下按钮,就会产生一个鼠标事件,按钮会产生一个单击信号。事件可以理解为发出信号的来源,信号的生产者,有了这个鼠标事件产生了这个单击信号。

1.2  事件和信号的区别

仔细来看,事件与信号其实并无多大差别,都是通过触发和响应函数来处理用户的请求。主要区别如下:

(1)    接收者不同

信号的接收者是槽,事件的接收者是一个队列,事件发生时,会产生一个事件对象被插入队列的尾部,系统会循环从队列的头部取事件对象进行处理。事件处理可以是异步的,信号的处理则是同步的。

(2)    单线和多线性

一个信号触发后,可以关联多个槽,多个槽会被执行,当然一个信号也可以触发另外一个信号。而事件则是与窗口相关的,所以事件回调时都是从当前窗口开始,一级一级向上派发,直到有一个窗口返回true,截断了事件的处理为止。

(3)    返回值作用

事件处理函数如果返回true,则这个事件处理已完成,QApplication会接着处理下一个事件,而如果返回false,那么事件分派函数会继续向上寻找下一个可以处理该事件的注册方法。信号处理函数的返回值对信号分派器来说是无意义的。

1.3  事件的接收和处理方法

1.3.1            事件传递逻辑

QT中事件的接收流程如下图所示,postEvent会将事件插入事件队列,异步处理事件,sendEvent直接将事件发出进行处理。如果返回TRUE或者调用accept(),说明事件已经处理完,不会在想父组件传播,如果返回FALSE或者调用ignore()表明这个事件没有被处理完,QT会传递给其父组件继续处理。

1.3.2            自定义事件处理函数

要实现自定义的事件处理函数,可以按照上图的流程,从流程中的某个点着手,将事件接收过来处理。

(1)   重写事件响应函数

例如widget类继承于QWidget,QWidget有keyPressEvent函数,但是widget类重写了keyPressEvent函数,会覆盖基类的函数。按钮按下时,widget的keyPressEvent函数先处理事件。这种方法的局限性是只能处理特定的事件。

void AlarmCenter::keyPressEvent(QKeyEvent *event)

{

if (event->key() == 0x01000000)

{

int i = 1;

}

else {

//将除了Esc的按键返回给父控件QWidget处理

QWidget::keyPressEvent(event);

}

}

(2)重写QObject类的event函数

bool QWidget::event(QEvent *event)

{

if (e->type() == QEvent::KeyPress)

{

QKeyPressEvent *keyEvent = (QKeyEvent *)event;

return false;

}

return true;

}


(3)安装过滤器Filter过滤消息,

可以在QObject或者QApplication上安装过滤器。AlarmCenter的构造函数中安装过滤器installEventFilter(this);然后在类中实现eventFilter函数即可。

bool AlarmCenter:: eventFilter (QObject *target, QEvent *event)

{

if (event->type() == QEvent::KeyPress)

{

int i = 1;

return true;

}

else {

//将除了Esc的按键返回给父控件QWidget处理

return QWidget::eventFilter(target, event);

}

}

(4)   重写QApplication的notify函数

先要自定义自己的MyApplication类,继承于QApplication,然后重写QApplication的notify函数,在notify函数内部建立过滤消息处理,如果要传递事件给其他部件,可以通过postEvent或sendEvent发送给其他部件。

自定义的Application类头文件如下:

#ifndef MYAPPLICATION_H

#define MYAPPLICATION_H

#include <QApplication>

#include <QEvent>

class MyApplication : public QApplication

{

public:

MyApplication(int & argc, char ** argv);

public:

bool notify(QObject *receiver, QEvent *e);//重写notify函数

};

#endif

自定义的Application类源文件如下:

#include "myapplication.h"

#include <QMouseEvent>

MyApplication::MyApplication(int & argc, char ** argv) : QApplication(argc, argv)

{

}

bool MyApplication::notify(QObject *receiver, QEvent *e)

{

//屏蔽MouseButtonPress、MouseButtonRelease和MouseMove事件

if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove)

{

//此处添加事件处理

return true;

}

return QApplication::notify(receiver, e);

}

1.4  定时器事件

1.4.1            QTimerEvent类实现定时器

(1)   用int id1 = startTimer(2000);函数启动定时器。

(2)   重写timerEvent函数,接收处理定时器事件

void  AlarmCenter::timerEvent(QTimerEvent *event)

{

if (event->timerId() == 1)

{

qDebug() << "1";

}

else

{

qDebug() << "not 1";

}

}

1.4.2            QTimer类实现定时器

(1)在源文件中添加头文件

#include<QTimer>

#include<QTime>

(2)在构造函数中添加代码新建QTimer对象,将QTimer::timeout信号关联到槽函数AlarmCenter::UpdateTimer,调用函数start启动定时器。

m_timer = NULL;

m_timer = new QTimer(this);

QObject::connect(m_timer, &QTimer::timeout, this, &AlarmCenter::UpdateTimer);

m_timer->start(1000);

(3)    实现定时器处理函数

void  AlarmCenter::UpdateTimer()

{

QTime time = QTime::currentTime();

QString str = time.toString("hh:mm");

}

1.4.3            只运行一次的定时器

采用QTimer::singleShot(10000,this,&AlarmCenter::UpdateTimer);10秒钟后会执行一次定时器。

1.5  事件过滤器

事件过滤器的作用是实现在一个部件中监控其他多个部件的事件,比如在一个QMainWindow中监控QMainWindow上面多个按钮、输入框、表格等多个部件的事件,进行逻辑分析处理。具体实现方式是通过Object的两个函数installEventFilter和重写函数eventFilter(QObject *target, QEvent *event)函数来接收事件,通过target参数来获取控件的对象,通过event参数来获取事件类型。这样在textEdit文本输入框中输入值的时候,只要键盘按钮按下,就会进入eventFilter中的keypress事件处理。

(1)  在构造函数中installEventFilter函数传入this指针,使得AlarmCenter作为textEdit的事件的接收者。

ui.textEdit->installEventFilter(this);

(2)  重写Qobject的eventFilter函数接收个控件的事件。

bool AlarmCenter::eventFilter(QObject *target, QEvent *event)

{

if (target==ui.textEdit)

{

if (event->type() == QEvent::KeyPress)

{

int i = 1;

return true;

}

else {

//将除了Esc的按键返回给父控件QWidget处理

return QMainWindow::eventFilter(target, event);

}

}

else

{

return QMainWindow::eventFilter(target, event);

}

}

1.6  SendEvent和postEvent的异同

1.6.1            函数的继承关系和属性

QApplication 继承于QGuiApplication,而QGuiApplication继承于 QCoreApplication,实际上这两个函数是QCoreApplication的静态函数。可以使用QApplication::sendEvent直接调用。

static bool sendEvent(QObject *receiver, QEvent *event);

static void postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority);

1.6.2            两个函数的异同

Sendevent会立即处理事件,在栈上创建临时事件变量,传入指针,调用结束后自动销毁。PostEvent函数则是先把事件放到事件队列中,需要在堆上创建,需要new。等到事件被处理完后,事件队列自动清除内存。例如我们创建一个spinBox,即带上下按钮的输入框。将QTdesigner中将取值范围设置为正负10000。然后通过自定义的按钮按下信号去控制spinBox的值发生变化。

控制spinbox向上按钮,使数字加1,如果放在定时器中,则会定时增加数值。

QKeyEvent myEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);

QApplication::sendEvent(ui.spinBox, &myEvent);

采用postEvent控制spinbox向下按钮,使数字减1,如果放在定时器中,则会定时减少数值。

QKeyEvent* myEventde=new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);

QApplication::postEvent(ui.spinBox, myEventde);

QT---事件系统的更多相关文章

  1. Qt 事件系统浅析 (用 Windows API 描述,分析了QCoreApplication::exec()和QEventLoop::exec的源码)(比起新号槽,事件机制是更高级的抽象,拥有更多特性,比如 accept/ignore,filter,还是实现状态机等高级 API 的基础)

    事件系统在 Qt 中扮演了十分重要的角色,不仅 GUI 的方方面面需要使用到事件系统,Signals/Slots 技术也离不开事件系统(多线程间).我们本文中暂且不描述 GUI 中的一些特殊情况,来说 ...

  2. Qt事件系统基本概念

    (转自:http://www.cnblogs.com/andy1987/p/3322059.html) 1. QT事件系统 Qt应用程序的消息处理是基于事件驱动的,程序的每个动作都是由某个事件所触发的 ...

  3. Qt事件系统之五:事件过滤器和事件的发送

    Qt提供了事件过滤器来实现在一个部件中监控其他多个部件的事件.事件过滤器与其他部件不同,它不是一个类,只是由两个函数组成的一种操作,用来完成一个部件对其他部件的事件的监视.这两个函数分别是 insta ...

  4. Qt事件系统之四:定时器事件与随机数

    一.定时器事件和随机数 QTimerEvent类用来描述一个定时器事件.对于一个QObject的子类,只需要使用int QObject::startTimer ( int interval)函数来开启 ...

  5. Qt事件系统之三:键盘事件

    QKeyEvent类用来描述一个键盘事件.当键盘按键被按下或者被释放时,键盘事件便会被发送给拥有键盘输人焦点的部件. QKeyEvent的key()函数可以获取具体的按键,对于Qt中给定的所有按键,可 ...

  6. Qt事件系统之二:鼠标事件和滚轮事件

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

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

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

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

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

  9. 用ISO C++实现自己的信号槽(Qt另类学习)

    qtc++objectsignalclassstring   目录(?)[-] Qt信号与槽 引入元对象系统 建立信号槽链接 信号的激活 槽的调用 全家福 零零散散写在后面 Q_OBJECT Conn ...

  10. Qt 学习之路 :Qt 绘制系统简介

    Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类. QPainter用来执行绘制的 ...

随机推荐

  1. 最新版Postman的下载及安装

    1. 操作环境 Windows Windows 7旗舰版 64位  , Windows 10专业版 Postman Postman-win64-5.1.3-Setup.exe 2. Postman的资 ...

  2. HTTP小幺鸡接口管理工具安装与配置说明

    http://www.xiaoyaoji.cn/doc/TxybXPTdx 小幺鸡接口管理工具安装说明 使用可以参考:https://blog.csdn.net/qincidong/article/d ...

  3. 爬虫的基本操作 requests / BeautifulSoup 的使用

    爬虫的基本操作 爬虫基础知识 什么是爬虫? 在最开始,还没有诞生Google和百度等一系列搜索引擎的公司的时候,人们进入一些公司的网站只能通过在浏览器地址栏输入网址的方式访问,如同在很早之前前手机不流 ...

  4. 接口自动化(atp,utp)

    atp:数据驱动 utp:代码驱动 pip install -r file.txt #安装文件里面有的模块 pip freeze > file.txt #导出你已经安装好的第三方模块

  5. Installing Jenkins as a Windows service

    Install Jenkins as a Windows service NOTE: if you installed Jenkins using the windows installer, you ...

  6. android linux 休眠 深度睡眠 查看 方法 调试【转】

    本文转载自:https://blog.csdn.net/u011006622/article/details/72900552 在Android移动设备中,有时按下Power键(未接电源,USB)时, ...

  7. sqlitestudio

    SQLite数据库的特性 特点: 1.轻量级2.独立性,没有依赖,无需安装3.隔离性 全部在一个文件夹系统4.跨平台 支持众多操作系统5.多语言接口 支持众多编程语言6.安全性 事物,通过独占性和共享 ...

  8. 待续未完- 自己写后台内容管理程序 - 用tp框架 和 前台 jquery ui等写的

    在日常开发中,我们主要使用的还是 php 的 内部的 语言本身提供的函数/常量,系统内部数组等. 为了和后面的tp框架提供的 "系统函数.系统常量"相区别,把php提供的东西叫语言 ...

  9. 重要, 要播放音乐视频等多媒体: 安装fedora23中的多媒体编码器

    区分: 大多数用户和高级用户? 删除 dnf remove software-name 启动软件管理器: gnome-software. 要删除系统 "自带的" 软件, 如empt ...

  10. 网络流24题 P2754 [CTSC1999]家园

    思路 如图,建立分层图跑dinic 每次在残余网络里加边继续跑 跑到ans>=k时候的i就是答案 诶呀啊,忘记弄箭头了,最后一列是向上的箭头,不过聪明的你们应该没啥影响 代码 #include ...