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才可以接受键盘事件.有输入焦点的窗口是活动窗口 ...
随机推荐
- 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 ...
- python pygame实现简单的网游
此示例为简单的实现游戏服务器端和客户端的消息同步,使用自定定义协议,引入了twisted网络框架,还有诸多不足(其实就是半成品). 资源下载地址: http://download.csdn.net/d ...
- 反转链表(python3)
问题描述: 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL解法1: ...
- MySQL笔记(1)
数据库和 SQL 概念 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它的产生距今已有六十多年.随着信息技术和市场的发展,数据库变得无处不在:它在电子商务.银行系统 等众多领域 ...
- 大数据-02-Scala入门
Scala 简介 它是一门基于JVM的面向函数和面向对象的编程语言, 它包含了求值表达式,闭包,切片操作,模式匹配,隐式转换等特性. 可变量/不可变量 可变集合/不可变集合.集合操作 函数 值函数 求 ...
- [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 ...
- Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)
(本套题算是比较温和吧,就是罚时有点高. B .Baby Bites 题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组. 思路:从左往右依次固定,看是 ...
- js中将一个字一个字的打印出来
第一种方式: setTimeout(function(){ var cc=document.createTextNode(ss[i]) content.appendChild(cc) },3000)
- 《DSP using MATLAB》Problem 6.9
9月9日,我们怀念毛主席! 代码: %% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...
- oracle命令导入SQL脚本
使用@导入 比如说我在oracle家目录下有a.sql文件 命令行sqlplus / as sysdba,进入后 SQL>@/home/oracle/a.sql; 回车搞定