Qt事件机制

文章目录

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

1 事件机制

事件传递图:
Qt事件机制_第1张图片

记录一下事件的传递顺序,主要围绕 QEventFilter, QEvent, QKeyEvent等事件展开:
首先自定义一个继承于QLineEdit的类MyEdit

#include 
#include "ui_testwidgetradius.h"
#include "myedit.h"
#include 
class CTestWidgetRadius : public QWidget
{
	Q_OBJECT
public:
	CTestWidgetRadius(QWidget *parent = Q_NULLPTR);
protected:
	void keyPressEvent(QKeyEvent *event);
private:
	Ui::CTestWidgetRadiusClass ui;
	MyEdit* myEdit = nullptr;
};
#include "testwidgetradius.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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";
}
#include 
#include 
#include 
class MyEdit : public QLineEdit
{
	Q_OBJECT
protected:
	void keyPressEvent(QKeyEvent *);
public:
	MyEdit(QWidget *parent);
	~MyEdit();

};
#include 
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)的内容,这个内容里面就包含了输入的一些处理,所以要想实现自己的代码,又想要实现父类的功能,就需要调用父类的函数,如下所示:

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

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

2 ignore 和 accept

修改代码如下:

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类里面实现这个函数:

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函数,并给控件安装过滤器

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

你可能感兴趣的:(燃犀的QT笔记,qt,开发语言)