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,事件就终止了。

相关推荐
Jayden_Ruan1 天前
C++逆向输出一个字符串(三)
开发语言·c++·算法
不吃鱼的羊1 天前
启动文件Startup_vle.c
c语言·开发语言
VBA63371 天前
VBA之Word应用第四章第二节:段落集合Paragraphs对象(二)
开发语言
点云SLAM1 天前
C++ 常见面试题汇总
java·开发语言·c++·算法·面试·内存管理
xiaowu0801 天前
策略模式-不同的鸭子的案例
开发语言·c#·策略模式
edjxj1 天前
Qt图片资源导入
开发语言·qt
qq_25929724731 天前
QT-事件
开发语言·qt
专注VB编程开发20年1 天前
CSS 的命名方式像是 PowerShell 的动词-名词结构,缺乏面向对象的层级关系
开发语言·后端·rust
古译汉书1 天前
嵌入式铁头山羊stm32-ADC实现定时器触发的注入序列的单通道转换-Day26
开发语言·数据结构·stm32·单片机·嵌入式硬件·算法
DreamLife☼1 天前
Qt 中的 Q_OBJECT 宏详解 —— 从源码到底层机制的全面剖析
qt·信号·qml·q_object··rtti·运行时类型信息