QTimer计时速度不断加快问题和QT中show函数失效问题的思考和处理

使用QT所遇问题之QTimer和show

一。 QTimer计时速度不断加快问题

1. 问题的发现

项目需要添加“延时登录”功能,但是在测试过程中发现此功能会时常失效。

2.问题解决的思路

(1)梳理整个功能实现的逻辑

退出设置界面的时候,打开定时器,设置相关参数logout_time_count(此参数决定延时时间),定时器时间到达之后进入中断,中断中logout_time_count–,直到logout_time_count值为0,将定时器停止,并退出登录。直到下一次退出设置界面时,再开始定时器的计时。

(2)监控进入定时器中断的次数

通过LOGD方式实时监控进入定时器中断的次数,发现每秒(定时器时间为1s)会多次进入中断函数,判断可能是定时器的值没有刷新导致不断进入定时器中断函数。(此处判断错误。事实上,如果定时器的计数没有清零和刷新,定时器不会多次进入中断而是会延长进入中断的时间)

(3)跟踪参数logout_time_count的值

通过LOGD的方式实时显示logout_time_count的值于日志上,观察其变化规律,发现每一次退出设置界面之后logout_time_count参数的值下降的速度就会增加一倍。 此现象与并行运行的情况非常相似,所以猜想是否是定时器并行运行导致的速度计时速度加快。

(4)QTimer定时器的timeout函数的并行运行

查找资料,发现QTimer的timeout多函数的并行执行这个作者遇到的问题与我的问题相似,受这篇博文启发,发现问题的核心就是connect函数的问题。因为原程序在逻辑上是在每次退出设置界面的时候都运行一次connect函数:connect(&logout_timer, SIGNAL(timeout()), this, SLOT(logout_timer_slots()));而每一次执行这行代码都会给定时器增加一个新的槽函数,以至于每次定时器中断都会并行运行多个槽函数,从而导致logout_time_count参数递减的速度加快(在槽函数中logout_time_count–)。

(5)修改程序

既然问题在于"每次退出设置界面的时候都会执行connect函数导致多个槽函数并行运行",那么就让程序只在第一次退出设置界面的时候才执行这行代码就可以解决问题了:

	if(is_fist_enter_settingwidgt==true)
	{
	    connect(&logout_timer, SIGNAL(timeout()), this, SLOT(logout_timer_slots()));
		is_fist_enter_settingwidgt = false;
	}

(6)总结

在QT中,如果多次执行connect函数可能会导致“当一个信号发出时会触发多个相同的槽函数并行运行”,而反过来讲,这并不一定是坏事,如果我们想要实时地并行执行某些函数的时候可以考虑用多次执行connect的方式来实现。

二。返回主窗口时界面卡住不动问题

1. 问题的发现和问题概要

在从设置界面退出到主窗口的时候,会不规律地出现“界面卡住不动,界面不刷新”的问题。初步判断是退出设置界面的时候发生线程冲突,导致主线程堵塞。

2. 问题解决的思路

(1)梳理在设置界面中按下返回键的一瞬间的逻辑以及程序运行了哪些代码。

(2)一般情况系统出现卡死的原因

一是系统在执行耗时程序甚至陷入了死循环导致卡死;二是出现内存泄漏导致主线程堵塞。

(3)监控程序运行

通过输出日志的方式来监控程序运行,找出程序卡死的位置。结果发现,退出到主窗口的整个过程都顺利进行,没有任何地方出现卡死的地方。也就是程序已经执行了“进入主窗口”的代码。

(4)查看线程状态

查看线程状态的方法可参考我之前的博文2020.9.28(查看线程状况、对象的概念、AutoLock类的作用),但是由于不能实时看得到线程的状态,而且我本身对于线程的知识也不足,所以这个过程中没有得到很大的收获,也没找到问题出现的原因。

但是,在操作系统的时候发现,虽然画面卡住了,但是主窗口中的一些功能还是能够实现,这应该可以说明主线程并没有卡住,而是主线程一些功能失效了。

(5)找出主窗口哪些功能仍然可用,哪些功能不能使用

1)仍然可用的功能:遥控键盘控制,控件事件,可以凭借记忆操控遥控重新进入设置界面。
2)失效的功能:主窗口的显示(包括键盘事件触发显示其他窗口的功能也失效),QopenGL渲染功能失效等。

在这个过程中意外发现:在登录弹出数字键盘的一瞬间,主窗口所有功能恢复,而且在卡住时进行的涉及OpenGL的键盘操作都在这一瞬间起效。

(6)跟踪QOpenGL功能的整个过程

由上面现象可知,主要失效的就是显示和渲染部分的功能,于是进行QOpenGL功能的跟踪,梳理这部分的逻辑,在每个节点设置一个日志输出,运行程序就可以跟踪这部分程序运行的过程。
然而在我梳理完这部分的逻辑且加上日志打印信息并运行的时候,发现程序根本没有进入paintGL函数中。(QOpenGL的机制就是每执行一次update()函数,就会自动运行paintGL中的代码,而本系统在每次视频流来的时候都会执行一次update()函数)【此处效率不高,应当按顺序一部分一部分地跟踪,而不是一下子给整个过程都加上了日志信息,从而浪费了相当一部分的时间

(7)监控从接收视频流到进入paintGL的过程

发现视频流成功接收,发出信号后,也进入了对应的槽函数,在这个槽函数中也运行了update()代码,所以根据QOpenGL的机制,理应进入paintGL中。所以现在的问题就是:为何执行了update代码,但是没有按照QOpenGL的机制进入painGL函数。

(8)寻找“QT调用update后不进paintGL”的原因

原来,update函数控制窗口重绘(重绘事件发出就能进入paintGL函数)的过程是:窗口系统为了提高性能,会尽量减少绘制次数和范围,所以默认情况下,只有窗口内容显示出来的时候才进行一次绘制,包括窗口被遮挡的部分重新显现。update和repaint就是主动通知系统绘制窗口内容。区别在于,update只是在内部数据中做一个标记,要等到主线程进行到下一次绘制时才进行绘制,所以多次调用update是没有意义的,只是重复设置绘制标记,并不会马上进行绘制,而且同样要等到你的代码走完之后走到绘制时才能看到结果

简单来说,update函数只是设置了一个绘制标志,需要先显示窗口,这个绘制标志才会生效,从而进入paintGL函数。

所以,现在的问题就变成:为何明明执行了show函数,窗口却没有显示呢?

(9)寻找“show函数失效的原因”

经过一段时间的资料查找后,还是没能知道show函数失效的原因,各位看到此处的朋友,如果有思路可以提供一下,我将不胜感激!!

(10)寻找“数字键盘出来的一瞬间主窗口恢复正常”的原因

1)数字键盘的出现可以使得主窗口的显示恢复正常,但是其他对话框(比如登录对话框)的出现并不能使得主窗口的显示恢复正常。
2)排查了数字键盘的有关功能,将其与登录对话框做对比,还是没能发现究竟数字键盘有何特殊可以使得主窗口恢复正常。
3)将show函数注释之后,发现在退出的时候就会出现一样界面卡住的问题,这又一次证明是show函数出了问题。在数字键盘出现的一瞬间,主窗口还是会显示出来,但是这个时候,界面是不动的(就也就是说OpenGL功能没有恢复),说明数字键盘的出现,只是将,本来执行了的但因为某种不知名原因而没有生效的show函数,给生效了。而不是数字键盘具有show函数的功能。或者说数字键盘的功能是完成了从显示设置界面到显示主窗口的切换

(11)在退出设置界面到主窗口的过程中显示数字键盘并马上隐藏

既然数字键盘显示之后可以使得主窗口正常显示,那么就在退出设置界面到主窗口的过程中,在show函数之后,显示数字键盘并马上隐藏,不就可以解决问题了?实践过后,事实证明这个办法可行,但是会有一个问题,在界面卡住问题的时候虽然可以自动解除,但是会有数字键盘一闪而过(如果没有出现界面卡住问题,平常不会有闪屏问题)。

3.总结

(1)问题出现的原因主要在show函数,执行了show函数却不知道什么原因show函数没有生效。

(2)问题通过“显示数字键盘并马上隐藏”的方法得到规避。

(3)数字键盘的出现,只是将,本来执行了的但因为某种不知名原因而没有生效的show函数,给生效了。而不是数字键盘具有show函数的功能。或者说数字键盘的功能是完成了从显示设置界面到显示主窗口的切换。

(4)数字键盘与show函数的内在逻辑关系还不能明确知悉,还有待探究,各位看到这里的朋友有什么想法思路,可以分享一下,我将不胜感激。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值