QTimer与事件循环理解

问题分析

最近在使用QT的时候发现了某些问题,查阅资料最后总结一下。我起初是想用QT在界面还在加载时加载一副动画,然后动画下面有加载的滚动条代表时间,由于测试所以界面加载没写很多东西很快就加载完成了。我就想让他加载慢点我看看效果。所以我想没过1秒就让滚动条进度加1。

问题解决

我定义一个QTimer变量让他在一边计时,每过多久就给我传过来一个数据。由于QSplashScreen在窗口初始化完成后就会消失,所以我不得不在住线程里面用个while让他在主窗口显示前阻塞在那里。这样的话就得开一个线程让QTimer进行计时。然后就逐步调入坑中…。通过qDebug() << "Thread_Time: " << QThread::currentThreadId();逐步打印线程id最终发现只有run()中的操作才在新的线程中。所以我在run()中加入如下代码:

void myThread::run()
{	
	QTimer* timer = new QTimer();
	qDebug() << "run() : " << QThread::currentThreadId();
	timer->setInterval(10);
	connect(timer, SIGNAL(timeout()), this, SLOT(StartTime()),Qt::DirectConnection);//Qt::DirectConnection 重要
	timer->start();
	exec();//重要
	return;
}
void myThread::StartTime()
{	
	if (indx > 100)
	{
		quit();
		return;
	}
	QMutexLocker locker(&mutex);
	indx++;
	emit TimeChanage(indx);
	qDebug() << "myThread::StartTime() : " << QThread::currentThreadId();
}

connect中第五个参数不能使用默认的,因为信号的发送者和接收者不在同一个线程中。void myThread::StartTime()还在父线程中而run()中的内容在新的线程中,所以要用Qt::DirectConnection,你可以理解为他的作用是当接收到信号时,他就直接调用槽函数,不需要进行事件的循环。如果用默认的话(由于发送者和接收者不在一个线程中)那么他会匹配使用Qt::QueuedConnection,这样的后果是槽函数不会立刻被调用,他会进入主程序的事件循环中,由于我主程序已经阻塞了所以他永远都掉不了槽函数。并且QTimer的运行依赖于事件循环,所以新的线程中要自己手动的开启事件循环exec()。

QTimer事件循环的理解

QTimer的运行依赖于事件循环,计时器不会自行启动线程或事件循环。在没有事件循环的情况下,它不会做任何事情。调用QTimer::start()后仅仅是在系统的定时器向量表中添加了一个定时器对象,但定时器并没有真正开启。使用start()方法,您只是告诉QTimer,当事件循环存在时,必须启动QTimer的逻辑,如果没有事件循环,则QTimer将无法工作。定时器的开启需要通过processEvent()开始的一系列调用后才会真正得开启,这个过程中会处理定时器向量表中所有的定时器对象。那么实际exec()中也是在不断地调用processEvent()方法。

最终效果

在这里插入图片描述
下面这个滚动条会一秒增加一格,由于我主线程阻塞了所以他在加载的过程中点不了其他的东西,不过在实际的运用中不会这样写,在实际的运用中先获去需要初始化的窗口数然后利用for循环和QDateTime::currentDateTime()来实现滚动条的加载。https://github.com/xu6666/QTimer-.git

结论

QTimer的运行依赖于事件循环,上面出现的问题是我自己写一个deom遇到的,在正常的项目中不会出现这种问题。
后续我会将源码贴上。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在一个 for 循环中使用 QTimer 是可能的,但是需要注意一些问题。由于 QTimer 是一个异步定时器,即它会在一个单独的线程中运行,并在定时器超时时发送信号,因此在使用 QTimer 时需要注意一下几点: 1. QTimer 可能会在循环中多次触发,因此需要考虑如何避免重复触发。可以通过设置 QTimer 的单次触发模式来解决这个问题。 2. QTimer 在定时器超时时发送信号,因此需要在一个槽函数中处理定时器超时事件,而不能在循环中直接处理定时器超时事件。 下面是一个使用 QTimer 的 for 循环的示例代码: ```cpp #include <QTimer> #include <QDebug> void MyClass::myMethod() { QTimer timer; timer.setInterval(1000); // 设置定时器间隔为1秒 timer.setSingleShot(true); // 设置单次触发模式 connect(&timer, &QTimer::timeout, this, &MyClass::onTimerTimeout); // 连接定时器超时信号和槽函数 for (int i = 0; i < 10; i++) { qDebug() << i; timer.start(); // 启动定时器 QEventLoop loop; // 创建一个事件循环 loop.exec(); // 进入事件循环,等待定时器超时信号 } } void MyClass::onTimerTimeout() { qDebug() << "Timer timeout"; } ``` 在这个示例代码中,我们创建了一个 QTimer 对象,并设置了定时器间隔和单次触发模式。然后,在 for 循环中,我们启动了定时器,并创建了一个事件循环,等待定时器超时信号的到来。当定时器超时时,会调用 onTimerTimeout() 槽函数,输出一条调试信息。这样,我们就可以在 for 循环中使用 QTimer 了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值