Qt事件机制

文章目录

  • [1 事件机制](#1 事件机制)
  • [2 ignore 和 accept](#2 ignore 和 accept)
  • [3 bool event(QEvent *event);](#3 bool event(QEvent *event);)
  • [4 bool eventFilter(QObject *watched, QEvent *event);](#4 bool eventFilter(QObject *watched, QEvent *event);)
  • [5 总结](#5 总结)

1 事件机制

事件传递图:

记录一下事件的传递顺序,主要围绕 QEventFilter, QEvent, QKeyEvent等事件展开:

首先自定义一个继承于QLineEdit的类MyEdit

cpp 复制代码
#include <QtWidgets/QWidget>
#include "ui_testwidgetradius.h"
#include "myedit.h"
#include <QKeyEvent>
class CTestWidgetRadius : public QWidget
{
	Q_OBJECT
public:
	CTestWidgetRadius(QWidget *parent = Q_NULLPTR);
protected:
	void keyPressEvent(QKeyEvent *event);
private:
	Ui::CTestWidgetRadiusClass ui;
	MyEdit* myEdit = nullptr;
};
cpp 复制代码
#include "testwidgetradius.h"
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QBitmap>
#include <QTextCodec>
#include <iostream>
#include <QToolTip>
bool CTestWidgetRadius::m_isHover = false;
QPoint CTestWidgetRadius::m_lastPoint = QPoint();
CTestWidgetRadius::CTestWidgetRadius(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
}

void CTestWidgetRadius::keyPressEvent(QKeyEvent *event)
{
	qDebug() << "parent keyPressEvent";
}
cpp 复制代码
#include <QLineEdit>
#include <QKeyEvent>
#include <QEvent>
class MyEdit : public QLineEdit
{
	Q_OBJECT
protected:
	void keyPressEvent(QKeyEvent *);
public:
	MyEdit(QWidget *parent);
	~MyEdit();

};
cpp 复制代码
#include <QDebug>
MyEdit::MyEdit(QWidget *parent)
	: QLineEdit(parent)
{
}

MyEdit::~MyEdit()
{
}

void MyEdit::keyPressEvent(QKeyEvent *event)
{
	 qDebug() << "myEdit keyPressEvent";
}

重写了keyPressEvent(QKeyEvent *event)这个函数之后,当我们在编辑框里面输入时,就会发现会触发这个键盘按下的事件,并且执行重写函数的代码,打印"myEdit keyPressEvent",但是此时并不能将你在键盘输入的字符显示在编辑框里面,这是因为你覆盖了QLineEdit的keyPressEvent(QKeyEvent *event)的内容,这个内容里面就包含了输入的一些处理,所以要想实现自己的代码,又想要实现父类的功能,就需要调用父类的函数,如下所示:

cpp 复制代码
void MyEdit::keyPressEvent(QKeyEvent *event)
{
	 qDebug() << "myEdit keyPressEvent";
	 QLineEdit::keyPressEvent(event);//调用父类的函数 以实现空间原本的功能
}

这个时候就发现,可以顺利的键入字符了。此时你会发现只打印了"myEdit keyPressEvent",并没有打印"parent keyPressEvent",那么如何将这个事件传递呢?

2 ignore 和 accept

修改代码如下:

cpp 复制代码
void MyEdit::keyPressEvent(QKeyEvent *event)
{
	 qDebug() << "myEdit keyPressEvent";
	 QLineEdit::keyPressEvent(event);//调用父类的函数 以实现控制原本的功能
	 event->ignore();//相当于 返回一个setAccepted(false) 传递事件给父类
}

此时就会打印myEdit keyPressEvent" 和 "parent keyPressEvent"了。这是因为调用ignore()只会这个事件就会被忽略,那这个事件就会继续传递,传递到他的父类去,也就是这里的Widget,就会执行父类的keyPressEvent(QKeyEvent *event)从而打印出"parent keyPressEvent"。

这里的 event->ignore();和setAccepted(false);作用是一样的。同理如果调用setAccepted(true);表示控件接收了这个事件,那么这个事件就不会继续传递了,和接受事件相对应的函数是event->accept();。

3 bool event(QEvent *event);

这个函数的级别是很高的,所有的具体的事件例如 void mousePressEvent(QMouseEvent *);

void keyPressEvent(QKeyEvent *);等事件,都会先由bool event(QEvent *event);函数来处理。接下来在myEdit类里面实现这个函数:

cpp 复制代码
bool MyEdit::event(QEvent *event) 
{
	if (event->type() == QEvent::KeyPress)
	{
		qDebug() << "myEdit event";
		return false;//返回true 就不会继续传递了,设置为false会传递给父类 
	}
};

这个时候会打印出"myEdit event" 和 "parent keyPressEvent",这是因为在event(QEvent *event) 函数中返回了false,表示这个控件不接收这个事件,那么这个事件就会继续传递到父类去,如果这里接受了事件,那么事件就不会传到父类去了。

4 bool eventFilter(QObject *watched, QEvent *event);

在窗口里面实现eventFilter函数,并给控件安装过滤器

cpp 复制代码
bool CTestWidgetRadius::eventFilter(QObject *watched, QEvent *event)
{
	if (watched == myEdit)
	{
		if (event->type() == QEvent::KeyPress)
		{
			qDebug() << "widget EventFilter";
			return false;
		}
	}
	return QWidget::eventFilter(watched, event);
}
cpp 复制代码
	myEdit = new MyEdit(this);
	myEdit->installEventFilter(this);

这个时候就会打印出

widget EventFilter

myEdit event

parent keyPressEvent

这是因为这里返回了false,表示没有myEdit不接收事件,那么这个事件就会传到event,因为event里面也返回了false,所以这个事件就会传到keyPressEvent(QKeyEvent *event),如果这个函数里面就收了事件,那么事件就停止传递,如果这个函数没有接收,那么这个事件会继续传递到父类。

5 总结

所以事件的传递顺序,是从eventFilter() ->event()-> MyEdit::keyPressEvent(QKeyEvent *event) ->QWidget::keyPressEvent(QKeyEvent *event).这个顺序传递的。当然如果其中一个环节返回了true,事件就终止了。

相关推荐
程序猿进阶2 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_433618444 分钟前
shell 编程(二)
开发语言·bash·shell
charlie11451419119 分钟前
C++ STL CookBook
开发语言·c++·stl·c++20
袁袁袁袁满19 分钟前
100天精通Python(爬虫篇)——第113天:‌爬虫基础模块之urllib详细教程大全
开发语言·爬虫·python·网络爬虫·爬虫实战·urllib·urllib模块教程
ELI_He99925 分钟前
PHP中替换某个包或某个类
开发语言·php
m0_7482361133 分钟前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
倔强的石头10641 分钟前
【C++指南】类和对象(九):内部类
开发语言·c++
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Evand J3 小时前
LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度
开发语言·matlab