Qt事件与QTimerEvent

Qt事件与QTimerEvent

打开Qt Creator中的帮助文档,搜索QEvent类
在这里插入图片描述

可以看到

The QEvent class is the base class of all event classes. Event objects contain event parameters
QEvent类是所有事件类的基类。事件对象包含事件参数

点击more后可以了解更多,来剖析一下:

Qt的主事件循环(QCoreApplication::exec())从事件队列中获取本地窗口系统事件,将它们转换为QEvents,并将转换后的事件发送给QObjects。

我们知道,在我们Qt程序运行时,都会添加下面一行代码,使程序进入循环。实际上QApplication类就是继承了QCoreApplication。

QApplication.exec();

也就是说,在Qt程序开始运行以后,程序就已经在不断地获取本地窗口系统事件,并将事件放入一个事件队列中。接着通过exec()将队列中的事件转换为QEvents类,并发送给QObjects;QObjects通过调用QObject::event()函数来接收事件,默认情况下,事件会被分派到事件处理程序。事件处理函数有例如 QObject::timerEvent() 定时器事件、QWidget::mouseMoveEvent() 鼠标事件。 installEventFilter()允许一个对象拦截目标为另一个对象的事件。

The basic QEvent contains only an event type parameter and an “accept” flag. The accept flag set with accept(), and cleared with ignore(). It is set by default, but don’t rely on this as subclasses may choose to clear it in their constructor.
Subclasses of QEvent contain additional parameters that describe the particular event.

一个基本的QEvent只包含一个标志,这个标志用accept()表达接受,用ignore()清除。

“它是默认设置的,但不要依赖于此,因为子类可能会选择在其构造函数中清除它。”
这句话的意思是,不要依赖于默认的设置,因为子类可能会选择在其构造函数中清除它,使得它在父类中失效。
换句话说,不希望子类在处理该事件时选择ignore()清除事件,而是将这个事件向上传递,以确保父类能够接收到这个事件。如果父类无法接受到这个事件,会存在一定的“危险”。




QTimerEvent Class

看一个QEvent类的子类: QTimerEvent Class,被称为定时器事件。

计时器事件定期发送到已启动一个或多个计时器的对象。每个计时器都有一个唯一的标识符。计时器由QObject::startTimer()启动。

官方解释中提到计时器由startTimer()函数启动。
以下是startTimer()的函数描述:

Starts a timer and returns a timer identifier, or returns zero if it could not start a timer.
A timer event will occur every interval milliseconds until killTimer() is called. If interval is 0, then the timer event occurs once every time there are no more window system events to process.
The virtual timerEvent() function is called with the QTimerEvent event parameter class when a timer event occurs. Reimplement this function to get timer events.
If multiple timers are running, the QTimerEvent::timerId() can be used to find out which timer was activated

计时器事件将每隔毫秒发生一次,直到调用killTimer()。如果interval为0,则计时器事件在每次没有更多窗口系统事件需要处理时发生一次。
当计时器事件发生时,使用QTimerEvent事件参数类调用虚拟timerEvent()函数。重新实现此函数以获取计时器事件。
如果有多个计时器在运行,QTimerEvent::timerId()可以用来找出哪个计时器被激活了

//startTimer的函数声明
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);

也就是说,我们需要调用startTimer()函数来创建一个定时器,并返回定时器的id,启动计时器。QTimerEvent类下有一个虚函数timerEvent(),计时器会调用这个timerEvent()对事件进行处理。我们需要重写这个虚函数。

例子

EventTest.h

#pragma once

#include <QtWidgets/QWidget>
#include "ui_EventTest.h"

class EventTest : public QWidget
{
    Q_OBJECT

public:

    EventTest(QWidget *parent = Q_NULLPTR);


private:
	int i, j, myTimer1, myTimer2;	//i,j是两个计时器的记录次数
    Ui::EventTestClass ui;
	void timerEvent(QTimerEvent *); //重写timerEvent()函数
};

创建项目EventTest,以上是EventTest的类定义。重点注释处,创建两个变量i,j,用于记录计时器计时次数。myTimer1, myTimer2用于记录计时器编号。
timerEvent是虚函数,因此我们需要在类中重写该函数并实现。

实现的代码EventTest.cpp如下:

#pragma execution_character_set("utf-8")
#include "EventTest.h"
#include <QTimer>
#include <QEvent>
#include <QDebug>

EventTest::EventTest(QWidget *parent)
    : QWidget(parent)
{
	i = 0;
	j = 0;
	myTimer1 = startTimer(500);	//每距离50毫秒触发一次
	myTimer2 = startTimer(1000);
	/*返回的是一个id*/
	qDebug() << "myTimer2" << myTimer2;
	qDebug() << "myTimer1:" << myTimer1;

    ui.setupUi(this);
}
void EventTest::timerEvent(QTimerEvent *event) {
	if (event->timerId() == myTimer1) {
		i++;
		qDebug() << "myTimer1计时:第" << i << "次";
	}
	if (event->timerId() == myTimer2) {
		j++;
		qDebug() << "myTimer2计时:第" << j << "次";
	}if (j >= 5) {
		killTimer(myTimer1);
		killTimer(myTimer2);
	}
}

可以看到,只要是QObject的子类,都可以直接调用startTimer()创建一个计时器1,次数会返回当前计时器的id。

	myTimer1 = startTimer(500);	//每距离50毫秒触发一次
	myTimer2 = startTimer(1000);

打印结果如下:
在这里插入图片描述

接着在timerEvent的定义里写对事件的处理,定时器每隔所设定的事件就会执行一次timerEvent函数。如果只有一个计时器,QTimerEvent对象可忽略。即:timerEvent(QTimerEvent *)。

void EventTest::timerEvent(QTimerEvent *event) {

}
/*忽略event*/
void EventTest::timerEvent(QTimerEvent *) {

}

但是我们有两个计时器,因此需要先判断当前计时事件是由谁发出,因此需要通过event对象调用timerId()函数返回当前计时事件的计时器id。

if (event->timerId() == myTimer1) {
		i++;
		qDebug() << "myTimer1计时:第" << i << "次";
	}
if (event->timerId() == myTimer2) {
		j++;
		qDebug() << "myTimer2计时:第" << j << "次";
    }

由于我设定的间隔时间是500毫秒与1秒,因此打印的顺序应该是1:2.
打印结果如下:
在这里插入图片描述
2021 07 13
by zhzhang

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值