Qt事件与自定义事件处理

QObject 类是所有 Qt 对象的基类,是 Qt 对象模型的核心,所有 Qt 部件都继承自 QObject。
QObject 及其派生类的单形参构造函数应声明为 explicit,以避免发生隐式类型转换
QObject 类既没有复制构造函数也没有赋值操作符函数(实际上它们被声明为私有的),因此无法通过值传递的方式向函数传递一个 QObject 对象

每一个 QObject 对象只能有一个父 QObject 对象,但可以有任意数量的子 QObject 对象
A ma; B mb; C mc;
ma.setParent(&mb); //将对象 ma 添加到 mb 的子对象列表中,
ma.setParent(&mc); //该语句会把 ma 从 mb 的子对象列表中移出,并将其添加到
mc 的子对象列表中。setParent 函数见后文。
QObject 对象会把指向各个子对象地址的指针放在 QObjectList 之中。QObjectList 是QList<QObject*>的别名,QList 是 Qt 的一个列表容器

对象删除规则
①、基本规则:父对象会自动删除子对象。父对象拥有对象的所有权,在父对象被删除时
会在析构函数中自动删除其子对象。
②、手动删除子对象:当手动删除子对象时,会把该子对象从父对象的列表中移除,以避
免父对象被删除时该子对象被再次删除。总之 QObject 对象不会被删除两次。
③、当一个对象被删除时,会发送一个 destroyed()信号,可以捕捉该信号以避免对 QObject对象的悬垂引用。
继承关系
QObject -----QCoreApplication----- QGuiApplication----- QApplication
QCoreApplication:主要提供无 GUI 程序的事件循环
QGuiApplication:用于管理 GUI 程序的控制流和主要设置
QApplication:该类专门为 QGuiApplication 提供基于 QWidget 的程序所需的一些功能,主要用于处理部件的初始化

事件的接受和忽略

QEvent::accept()函数表示接受一个事件,调用 accept(),则事件不会传递给父对象
QEvent::ignore()函数表示忽略一个事件。调用 ignore()则事件会向父对象传递。
Qt 默认值是 accept (接受事件),在 QWidget 的默认事件处理函数(比如 keyPressEvent())中,默认值是ignore();

event() 函数中调用 accept()ignore() 是没有意义的,event()函数通过返回一个 bool值来告诉调用者是否接受了事件(true 表示接受事件)。
是否调用 accept()是用于事件处理函数与 event()函数之间通信的,
event()函数返回的 bool 值是用于与 QApplication::notify()函数之间通信的。

事件过滤器:

事件过滤器用于拦截传递到目标对象的事件
①、Qt 调用void QObject::installEventFilter (QObject* filterObj)把 filterObj 对象设置安装(或注册)为事件过滤器,filterObj 也称为过滤器对象。事件过滤器通常在构造函数中进行注册。
②、在上一步注册的 filterObj 对象,通过调用 bool QObject::eventFilter(QObject* obj, QEvent* e); 来接收拦截到的事件。也就是说拦截到的事件在 filterObj 对象中的 eventFilter 函数中处理。eventFilter的第一个参数 obj 指向的是事件本应传递到的目标对象。
③、使用 QObject::removeEventFilter(QObject *obj) 函数可以删除事件过滤器。若同一对象安装了多个事件过滤器,则最后安装的过滤器首先被激活

自定义事件与事件的发送

static void QCoreApplication::postEvent(QObject* receiver, QEvent* event, int priority=Qt::NormalEventPriority)
static bool QCoreApplication::sendEvent(QObject* receiver, QEvent* event)
参数解释:
receiver:
指向接收事件的对象
event:
表示需要发送的事件
priority:
表示事件的优先级,事件会按优先级排序,高优先级的事件排在队列的前面。其取值为枚举类型Qt::EventPriority 中的枚举值,如下:
Qt::HighEventPriority: 值为 1。
Qt::NormalEventPriority: 值为 0。
Qt::LowEventPriority: 值为-1。
优先级只是一个相对值,其值可取介于规定的最大值和最小值之间的任何值,比如可使 priority 参数的值为 Qt::HighEventPriority +10。

  1. 发布(post)事件:
    把事件添加到事件队列中,并立即返回。发布事件必须在堆(比如使用 new)上创建事件,因为事件被发布后,事件队列将获得事件的所有权并自动将其删除。发布事件后再访问该事件是不安全的。发布事件还可以对事件进行合并(或称为压缩),比如在返回事件循环之前连续发布了多个相同的事件,则这多个相同的事件会自动合并为一个单一的事件。可合并的事件有鼠标移动事件、调整大小事件等
  2. 发送(send)事件:
    把事件直接发送给接收事件的目标对象。事件发送之后不会被删除,发送的事件通常创建在堆栈上

自定义事件原理

  • 事件其实就是使用的一个整数值表示的,因此在创建自定义事件时,只须给事件指定一个整数值即可,在 Qt 中,这个整数值是通过枚举类型 QEvent::Type 定义的,事件的其他信息可以封装在一个自定义的类之中。
  • 自定义的事件即可以是预定义类型,也可以是自定义类型的。
  • 自定义类型的事件,需要定义一个事件编号,该编号必须大于 QEvent :: User(其值为1000),小于 QEvent::MaxUser(其值为 65535)。 各种事件不能重叠(即 QEvent::Type 类型的值不能相同),小于 QEvent::User 的事件是Qt 内部定义的事件,他们不会重叠,
  • 对于自定义的事件可以使用 registerEventType() 函数来保证事件不重叠,
    该函数原型如下:
    static int QEvent::registerEventType ( int hint = -1 );
    如果 hint 的值不会产生重叠,则会返回这个值;如果 hint 不合法,系统会自动分配一个合法值并返回。因此,可使用该函数的返回值创建 Type 类型的值

创建自定义事件的方法和步骤

  • 使用 QEvent 的构造函数创建事件,其原型为:QEvent(Type type);
    示例:
    QEvent::Type t1=(QEvent::Type)1333; //定义事件编号
    QEvent e(t); //创建事件 e
  • 使用 Qt 已创建好的事件类型创建事件,比如使用 QKeyEvent 类创建键盘事件。
  • 继承 QEvent 类,创建自定义事件。
  • 使用 QCoreApplication::postEvent()或 QCoreApplication::sendEvent()函数发送事件。
  • 可使用以下方法处理自定义事件:
    1.重写 QObject::event()函数,在该函数内直接处理自定义事件或调用自定义的事件处理函数处理事件。
    2.安装事件过滤器,然后在过滤器对象的 eventFilter()函数中处理自定义事件。还可以重写 QCoreApplication::notify()函数.

代码示例

QEvent::Type t1 = (QEvent::Type)1333;
//使用 QEvent 的构造函数在堆栈上创建自定义事件
QEvent e(t1); 

class E :public QEvent 
{
public: //子类化 QEvent 以创建自定义事件
	//方式 1:使用静态成员。
	
	//使用静态成员主要是为了正确初始化父类部分 QEvent,比如
	//E():t2((QEvent::Type)1324),QEvent(t2){},若 t2 不是静态的,则则初始化之后 t2 为 1324,但传递
	//给 QEvent 的 t2 是一个不确定的值,因为按照 C++规则,对父类部分的初始化先于数据成员的初始化。	
	//注意:不要使用名称 t,因为 QEvent 类之中有一个名称为 t 的成员变量。
	static QEvent::Type t2; 

	E() :QEvent(t2) {}


	//方式 2:使用带一个参数的构造函数
	QEvent::Type t3;
	explicit E(QEvent::Type t4) : QEvent(t4),t3(t4)
	{}
};

QEvent::Type E::t2 = (QEvent::Type)1334;

class A :public QWidget 
{
public:
	bool event(QEvent* e)	//重写 event 函数以处理自定义事件
	{ 
		if (e->type() == t1) //判断事件类型是否为 t1
		{
			cout << "AE" << e->type() << ",";
			f1((E*)e); //调用自定义的处理函数处理该事件
			return 1;
		}
		if (e->type() == E::t2) 
		{ 
			cout << "BE" << e->type() << ","; 
			f2((QEvent*)e); 
			return 1; 
		}
		if (e->type() == ((E*)e)->t3)
		{ 
			cout << "CE" << e->type() << ","; 
			f3((E*)e);
			return 1;
		}
		return QWidget::event(e);
	} //event 结束
	//以下为处理自定义事件的事件处理函数
	void f1(E* e) 
	{ 
		cout << "F1" << endl; 
	}
	void f2(QEvent* e) 
	{ 
		cout << "F2" << endl; 
	}
	void f3(E* e) 
	{ 
		cout << "F3" << endl; 
	}
}; //类 A 结束。

int test(int argc, char* argv[])
{
	QApplication aa(argc, argv);
	A ma;
	E me; 
	E* pe = new E((QEvent::Type)1335);
	//发布或发送事件
	aa.sendEvent(&ma, &e); 
	aa.sendEvent(&ma, &me); 
	aa.postEvent(&ma, pe);

	//aa.postEvent(&ma,&me); //错误,发布的事件 me 必须是在堆上创建的。
	ma.resize(333, 222);
	ma.show();
	aa.exec(); 
	return 0;
}

//运行程序后,输出结果依次为 AE1333, F1 BE1334, F2 CE1335, F3	

使用事件过滤器处理自定义事件

QEvent::Type t1 = (QEvent::Type)QEvent::registerEventType(1333);
//使用 QEvent 的构造函数创建自定义事件
QEvent e1(t1); 

//t2 的值与 t1 重复,使用 registerEventType 会自动产生一个合法的值
QEvent::Type t2 = (QEvent::Type)QEvent::registerEventType(1333);
QEvent e2(t2);

class A :public QWidget 
{
public:
	bool event(QEvent* e) 
	{
		if (e->type() == t1) 
		{ 
			cout << "AE" << e->type() << ",";
			f1((QEvent*)e); 
			return 1; 
		}
		if (e->type() == t2) 
		{ 
			cout << "BE" << e->type() << ","; 
			f2((QEvent*)e); 
			return 1; 
		}
		return QWidget::event(e);
	} //event 结束

	void f1(QEvent* e) { cout << "F1" << endl; }
	void f2(QEvent* e) { cout << "F2" << endl; }
};
class B :public QObject
{
public:
	bool eventFilter(QObject* w, QEvent* e) 
	{
		if (e->type() == t1) 
		{
			cout << "A" << endl; 
			return 1; 
		}
		if (e->type() == t2) 
		{ 
			cout << "B" << endl;
			return 0; 
		}
		return 0;
	}
};
int main(int argc, char* argv[]) 
{
	QApplication aa(argc, argv);
	A ma; B mb;
	ma.installEventFilter(&mb); //安装事件过滤器
	aa.sendEvent(&ma, &e1); 
	aa.sendEvent(&ma, &e2);
	ma.resize(333, 222);
	ma.show(); 
	aa.exec(); 
	return 0;
}

本例依次输出 A B BE65535,F2, 其中 65535 为使用 registerEventType 函数为 t2 分
配的合法的数值。可见,安装事件过滤器之后,发送的事件 e1 和 e2 会使用过滤器对象的
eventFilter 函数进行处理
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值