Qt 中的事件处理(一)


- 基于操作系统才能运行
- GUI应用程序提供的功能必须由用户触发
- 用户操作界面时操作系统是第一个感知的
- 系统内核的消息通过事件处理转变成QT的信号
谁来产生事件? 最容易想到的是我们的输入设备,比如键盘、鼠标产生的keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent事件(他们被封装成QMouseEvent和QKeyEvent)。
②Qt中事件的分发
对于Qt GUI程序,由QApplication来负责
类是整个Qt对象模型的心脏,事件处理机制是QObject三大职责(内存管理、内省(intropection)与事件处理制)之一。任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
- 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()函数主要用于事件的分发。
- 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();
}
#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 中的事件处理(一)的更多相关文章
- 第38课 Qt中的事件处理(上)
1. GUI程序原理回顾 (1)图形界面应用程序的消息处理模型 (2)思考:操作系统发送的消息如何转变为Qt信号 2. Qt中的事件处理 (1)Qt平台将系统产生的消息转换为Qt事件 ①Qt事件是一个 ...
- 第39课 Qt中的事件处理(下)
1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...
- Qt 中的事件处理(二)
1. 回顾事件传递的过程 ①源头:操作系统 操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中, ②应用程序收到系统消息后, 他会将系统消息翻译成对应的 ...
- Qt事件系统之一:Qt中的事件处理与传递
一.简介 在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的 ...
- 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中的事件
1. 引自---http://blog.sina.com.cn/s/blog_6e80f1390100pro4.html 信号和事件的区别就在与,事件比信号更加底层,而且如果一个信号对应多个槽的话,信 ...
- Qt中的键盘事件,以及焦点的设置(比较详细)
Qt键盘事件属于Qt事件系统,所以事件系统中所有规则对按键事件都有效.下面关注点在按键特有的部分: focus 一个拥有焦点(focus)的QWidget才可以接受键盘事件.有输入焦点的窗口是活动窗口 ...
随机推荐
- os与操作系统进行交互,sys解释器相关,random随机数,shutil解压和压缩
1.os 与操作系统相关 对文件的处理 对路径的处理 import os#主要用于与操作系统进行交互 掌握: print(os.makedirs('a/b/c'))#创建目录 可用递归创建 print ...
- python day08作业
- golang快速扫描
利用golang的并发优势快速扫描端口 Scanner startIp [endIp] port thread package main import ( "flag" " ...
- Spring Boot 揭秘与实战(二) 数据存储篇 - MySQL
文章目录 1. 环境依赖 2. 数据源3. 脚本初始化 2.1. 方案一 使用 Spring Boot 默认配置 2.2. 方案二 手动创建 4. 使用JdbcTemplate操作5. 总结 4.1. ...
- 【转载】 强化学习(七)时序差分离线控制算法Q-Learning
原文地址: https://www.cnblogs.com/pinard/p/9669263.html ------------------------------------------------ ...
- 20155208徐子涵 2016-2017-2 《Java程序设计》第5周学习总结
20155208徐子涵 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 第八章 异常处理 8.1 语法与继承结构 Java中所有错误都会被打包为对象,运用tr ...
- HPU1460: 杨八方的表面兄弟
题目描述 如果你之前关注过HPUOJ的话,那么你一定听说过杨八方的名字.在去年,很多同学共同见证了杨八方同学的填报志愿.来到学校.军训--或许你曾陪同杨八方一起思考过许多问题,又或者你是刚听说这个名字 ...
- 字符串转json格式
方法一:var json = JSON.parse(str)方法二:eval
- Linux,IDS入侵防御系统
https://www.comparitech.com/net-admin/network-intrusion-detection-tools/11 2018年的顶级入侵检测工具 https://op ...
- 【牛客练习赛22 C】
https://www.nowcoder.com/acm/contest/132/C 题目大意:在n个区间中取出n个数,相加的和一共会出现多少种结果. 题目分析:对于这种挑选数字相加,由于每一步不同的 ...