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 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer2 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良2 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
Kalika0-03 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
代码雕刻家3 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
一个闪现必杀技3 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm
Fan_web3 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
龙图:会赢的3 小时前
[C语言]--编译和链接
c语言·开发语言
威桑4 小时前
记一次控件提升后,运行却不显示的Bug
qt