Qt Timer 时钟
QObject
提供了时钟支持。最常见的用法就是当做事件触发器,当经过一段时间间隔后触发某个操作。
通过QObject::startTimer()
启动时钟,这个函数参数为一个整数,单位是毫秒,同时会返回一个时钟ID
。
通过向QObject::killTimer()
传入时钟ID
来停止这个时钟。
如果我们创建了QTimer
对象,也可以通过其成员方法start()
,参数与QObject::startTimer()
一样。
时钟机制的运行必须依赖事件循环,也就是说如果我们想要使用时钟就必须在某处开启事件循环。当时钟启动时,应用程序会发送一个QTimerEvent
,此时程序会跳出事件循环,直到这个事件被处理之后才会继续循环,这也就是说,如果我们的程序正在执行其他事件,则时钟事件就可能延后执行,导致时钟精确度降低。
多线程应用中也可以使用时钟机制。时钟在不同的线程的事件循环中会独立地推进,不能在一个线程中启动另一个线程的时钟。
例子:
study *w = new study();
QTimer *timer = new QTimer(w);
QObject::connect(timer, &QTimer::timeout, w, &study::update);
timer->start(1000);
这个例子会每隔1s
执行一次update
,当时钟触发时,会发送timeout
信号,因此通过信号槽的方式就可以进行某些操作。
这是创建QTimer
对象的方式来设置,那我们之前提到的QObject::startTimer()
并没有对象用于信号槽的连接,应该怎么做呢。此时可以通过QTimerEvent
事件处理来完成,这种方式要比信号槽方式更简单,不需要设置槽函数。
比如:
class study : public QMainWindow
{
Q_OBJECT
public:
study(QWidget *parent = nullptr);
~study();
void timerEvent(QTimerEvent *event);
private:
Ui::study *ui;
int timerId1;
int timerId2;
};
study::study(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::study)
{
ui->setupUi(this);
timerId1 = startTimer(1000);
timerId2 = startTimer(2000);
}
void study::timerEvent(QTimerEvent *event){
if(event->timerId() == timerId1){
qDebug() << "timer1";
}
else if(event->timerId() == timerId2){
qDebug() << "timer2";
}
else{
QObject::timerEvent(event);
}
}
上面的这两种方法都会周期性地执行某些操作,如果我们只需要执行一次,可以使用单发时钟singleShot
。
study *w = new study();
QTimer::singleShot(1000, w, &study::update);
相当于简化的信号槽。