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

举报
黑兔子 发表于 2022/08/02 13:59:10 2022/08/02
【摘要】 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()才可以。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。