Qt | 定时器实现动画效果时卡住了

简介: Qt通过使用定时器定时切换图片实现动画效果遇到的卡顿问题。

环境: VS2017+Qt5.14

实现功能: 一个QWidget窗口,初始状态是隐藏的,在这个QWidget中有一个QLabel, 在QWidget显示的同时,打开定时器,定时器时间间隔为42ms,在定时器响应函数中执行QLabel上图片的定时切换,从而达到动画的效果。

具体实现: QWidget执行show()之后,立马打开定时器,在定时器的timeout()中执行ui.label->setPixmap(m_Pixmap[i]);

遇到的问题: show()函数执行完毕,定时器start()执行完毕,但是定时器的响应函数迟迟不响应。有时可能等一两秒就可以反应过来,有时可能需要八九秒才可以反应过来,反应过来后,定时器正常运行,动画正常显示。或者在定时器不响应的时候,用鼠标在窗口上移动一下,定时器的响应函数就可以正常响应了。但是响应之前就像界面卡住了一样。

于是开始查找原因及解决办法,把所有相关代码注释掉后一点点放开,发现造成这种现象的原因就是因为调用show()函数引起的。这就有点鸡肋了,如果是因为show()函数引起的,说明是主线程在走UI的一些东西卡住了,这怎么解决?!

在网上查了很多种解释和方法,show()和hide()函数确实会引起界面刷新,从而导致主线程卡住,如果是静态页面,一般不会有什么问题,但是如果是动态页面,就会出现程序卡住的现象。

解决办法: 一种方法是使用stackWidget,调用stackWidget的setCurrentIndex()实现页面的切换,避免使用show()、hide()函数。我试过这种方法,但是因为我们的窗口样式和父子继承关系很复杂,所以stackWidget加入进来后,显示效果并不能达到我们的需求,所以放弃这种方法。

另一种方法是一个比较有局限性的方法,就是调用Qt的事件轮循机制。

m_bExit = false;
while (!m_bExit)
{
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

在需要退出事件轮循的地方将m_bExit = true;

调用事件轮循后,界面就不会出现卡死的现象了,因为在处理主进程的同时可以去处理其他的消息、事件。这样就实现了同时处理主进程和其他线程的事件,达到在线程中刷新界面的效果。

注:

因为我的这部分代码属于在show()的同时操作界面,所以即使开线程,也需要在线程中发信号出来,执行相应操作,所以如果用线程+信号槽机制还是会卡死。

目前上面这种方法是我试过的效果最好的方法,但是他会有一个问题,就是如果在这个while()循环执行期间退出程序,程序是退不掉的,需要手动调用m_bExit = true,或者销毁资源的函数,先退出while循环,然后再执行程序的close()才可以。

目录
相关文章
|
4月前
【qt】日历和定时器
【qt】日历和定时器
48 0
|
3月前
Qt定时器
Qt定时器
|
3月前
|
API
【Qt】Qt定时器类QTimer
【Qt】Qt定时器类QTimer
|
4月前
|
Linux 图形学
深入理解Qt定时器:QTimer的魅力与挑战(一)
深入理解Qt定时器:QTimer的魅力与挑战
2892 0
|
4月前
|
C++
QT定时器的使用timer示例
QT定时器的使用timer示例
|
4月前
|
安全 API 开发者
深入理解Qt定时器:QTimer的魅力与挑战(二)
深入理解Qt定时器:QTimer的魅力与挑战
366 0
|
4月前
|
编解码 算法 Unix
【Qt 应用开发 】QT 三种定时器的介绍 以及 QTimer startTimer/Timerevent QBasicTimer 之间的区别
【Qt 应用开发 】QT 三种定时器的介绍 以及 QTimer startTimer/Timerevent QBasicTimer 之间的区别
653 0
|
11月前
|
数据格式
嵌入式 QT 定时器与计时器
嵌入式 QT 定时器与计时器
Qt | 定时器的使用 QTimer
学习使用Qt定时器的用法。
904 0