请教一个大难题,qt怎么在一个fb基础下,一个线程画波形,一个线程主UI

qq_21042359 2020-09-03 03:33:36
我们都知道,UI都是只能一个线程的,我的嵌入式芯片不是很强,只有一个FB,用于QT的主UI线程。但是我有个很关键的需求,就是40ms实时刷新波形不能有任何卡顿,目前波形本身绘制是不占什么资源的,就几个点,但是其他东西在主线程绘制时,极大几率都会有超过40ms的情况,甚至几百毫秒,如果画波形的线程和它们在一起,就必然要等待,效果就是一卡一卡的。有没有什么思路方案能解决这个问题,改源码都可以的。双FB合成的方案我也试过了,虽然波形不卡了,但是合成速率=刷屏速率=帧数,和分辨率挂钩,结果就是整体UI变卡了,只能放弃,有没单UI单FB的方案?
...全文
10793 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_21042359 2020-09-29
  • 打赏
  • 举报
回复
引用 25 楼 weixin_32136305 的回复:
我提供个思路:你用一个线程专门采集数据,数据无变化也没关系,存储在你自己的缓冲区内。采集到一定程度(比如说25个)开始绘制、绘制只管提数据画点,不牵扯任何计算。这样的话它与实时会有1秒延迟(因为我假设是25个,25x40=1000毫秒,延迟大小取决于你的缓冲区大小)。但是理论上可以做到不卡。 这个思路是来自于直播视频处理,做视频流都是先刷缓冲区的,缓冲区里有数据才开始显示。这样会和直播室里有一点延迟,但是看视频的人是感觉不到的
谢谢你的建议,不过你的思路应该是解决绘制波形不卡UI,其实我的情况是反过来的,UI画太久把快速刷新的波形卡了,我们画波形每次就画几个像素点,是很快的,可以忽略不计。但是画UI就要很久了,我们其他控件也是定时刷新,弹出大菜单更是瞬间画很久,这个很久不是几秒那种,但是至少对于波形40ms的刷新,甚至25ms刷新来说,远远超过它的周期了。结果就是,明明轮到波形贴出来的时刻,却因为正在画其他东西而等待了,每次都这么等待,眼睛看到的波形就是一顿一顿的。
weixin_32136305 2020-09-27
  • 打赏
  • 举报
回复
我提供个思路:你用一个线程专门采集数据,数据无变化也没关系,存储在你自己的缓冲区内。采集到一定程度(比如说25个)开始绘制、绘制只管提数据画点,不牵扯任何计算。这样的话它与实时会有1秒延迟(因为我假设是25个,25x40=1000毫秒,延迟大小取决于你的缓冲区大小)。但是理论上可以做到不卡。 这个思路是来自于直播视频处理,做视频流都是先刷缓冲区的,缓冲区里有数据才开始显示。这样会和直播室里有一点延迟,但是看视频的人是感觉不到的
qq_21042359 2020-09-22
  • 打赏
  • 举报
回复
引用 22 楼 xqhrs232 的回复:
双缓冲有试过没?
你说的双缓冲是指什么?子线程画pixmap,信号槽发给主线程,然后主线程drawpixmap画出来么?其实并不能解决这个问题呢。。
xqhrs232 2020-09-19
  • 打赏
  • 举报
回复
双缓冲有试过没?
qq_21042359 2020-09-11
  • 打赏
  • 举报
回复
引用 18 楼 翅膀又硬了 的回复:
引用 17 楼 qq_21042359 的回复:
屏幕大概有一半的区域是绘制实时波形的,40ms定时绘制打点走动。其余区域有些是热键,有些是定时更新的其他参数数值矩形widget块。点开热键会弹出各个菜单。热键都是qpushbutton实现的,菜单里面还有很多qt控件,combobox, spinbox啊,qlabel啊之类的。new一个空白大菜单,show出来,少说主线程就要几十毫秒,这个过程,假如主界面其他widget也要update,那么波形看起来更加是一顿一顿的。
有用户交互的时候,卡顿一下算正常吧。没有交互的时候,你不主动去刷新界面,它不会刷新的呀。 你这个定时刷新的机制可以优化一下,改成有数据变化到时间再刷新,没变化就不用刷。
有数据变化才刷新,这些都是必做的,也已经做了,但是我们主界面除了波形以外,其他参数也是定时刷新的,数据什么时候改变无法控制,打开菜单窗口那些也是需要的。这些都会卡到波形
qq_21042359 2020-09-11
  • 打赏
  • 举报
回复
引用 19 楼 Italink 的回复:
引用 16 楼 qq_21042359 的回复:
[quote=引用 14 楼 Italink 的回复:]
嗯嗯,是挺麻烦的。或者应该更细致的去思考究竟是什么导致了界面的卡顿?通常情况下UI应该不会卡顿,只可能是短时间内有一个爆发性的占有提升,是否可能是因为一些不恰当的操作导致了一些关联操作?这些操作是否有必要,如果没有必要,可以想办法避免这些关联操作,如果有必要,再考虑是否可以延迟操作。代码是你写的,你肯定更清楚该怎么做。
代码没问题,直接用qwindow, new show就能耗时了,单核800MHz的嵌入式芯片,跑qt就是这个性能的,行业内龙头公司也是用这个芯片,UI也是这个性能,打开大窗口就是要比较久的时间,但是他们真的做到在UI干大活的时候(比如打开一个大窗口)波形一点都不卡。只打听到他们用钱砸的,把qt工程师请过去专门给他们优化的源码。
Italink 2020-09-10
  • 打赏
  • 举报
回复
引用 16 楼 qq_21042359 的回复:
[quote=引用 14 楼 Italink 的回复:]
嗯嗯,是挺麻烦的。或者应该更细致的去思考究竟是什么导致了界面的卡顿?通常情况下UI应该不会卡顿,只可能是短时间内有一个爆发性的占有提升,是否可能是因为一些不恰当的操作导致了一些关联操作?这些操作是否有必要,如果没有必要,可以想办法避免这些关联操作,如果有必要,再考虑是否可以延迟操作。代码是你写的,你肯定更清楚该怎么做。
翅膀又硬了 2020-09-10
  • 打赏
  • 举报
回复
引用 17 楼 qq_21042359 的回复:
屏幕大概有一半的区域是绘制实时波形的,40ms定时绘制打点走动。其余区域有些是热键,有些是定时更新的其他参数数值矩形widget块。点开热键会弹出各个菜单。热键都是qpushbutton实现的,菜单里面还有很多qt控件,combobox, spinbox啊,qlabel啊之类的。new一个空白大菜单,show出来,少说主线程就要几十毫秒,这个过程,假如主界面其他widget也要update,那么波形看起来更加是一顿一顿的。
有用户交互的时候,卡顿一下算正常吧。没有交互的时候,你不主动去刷新界面,它不会刷新的呀。 你这个定时刷新的机制可以优化一下,改成有数据变化到时间再刷新,没变化就不用刷。
qq_21042359 2020-09-10
  • 打赏
  • 举报
回复
屏幕大概有一半的区域是绘制实时波形的,40ms定时绘制打点走动。其余区域有些是热键,有些是定时更新的其他参数数值矩形widget块。点开热键会弹出各个菜单。热键都是qpushbutton实现的,菜单里面还有很多qt控件,combobox, spinbox啊,qlabel啊之类的。new一个空白大菜单,show出来,少说主线程就要几十毫秒,这个过程,假如主界面其他widget也要update,那么波形看起来更加是一顿一顿的。
qq_21042359 2020-09-10
  • 打赏
  • 举报
回复
引用 14 楼 Italink 的回复:
如果你需要更高性能的绘图,可以学一下Qt封装的QOpenGLWidget,不过需要3D图形基础,短期内很难掌握
这个没必要,因为我们波形区的波形绘图速度很快,占用资源少,反而是QT自带的控件,窗口占用比较高,是QT的UI卡了波形,不是波形卡了UI。总不可能把整个工程所有用到的qt控件,自己用qopenglwidget画一遍,所有逻辑实现一遍来代替qt自己的控件把。。。最多就是把qt的后端从linuxfb改为eglfs,然后编译的qt库支持opengles,不过这个也需要芯片厂家的驱动支持。实际上有没有这个并不会解决我说的问题,除非它能把我的UI所有绘图,从几十毫秒,几百毫秒,直接压缩到1毫秒,跟台电脑一样的速度,然而很可惜,这个CPU的图形卡做不到这个程度。
qq_21042359 2020-09-10
  • 打赏
  • 举报
回复
引用 13 楼 Italink 的回复:
我看你之前的回答,你说A需要0.01ms,B可能100ms,所以主线程可能40ms完成不了绘制导致卡顿,是因为你把大多事情都交给主线程了(比方说一些绘图的设置操作) 你需要做的是,主线程40ms定时刷新,每一次刷新都去绘制两张pixmap,不管这个pixmap里是什么。然后呢要做的就是在一个线程中以0.01ms去处理A对应的pixmap,以另一个线程以100ms来处理B对应的pixmap,这样就能保证主线程同步也不会出现卡顿
这个已经有点像我最开始说的双FB合成的方案。 我的运行平台是嵌入式芯片,单核800MHz,linux系统,只有一个framebuffer。 首先我们知道,qt自己的控件,都是默认paintevent绘制内容,且在主线程。我们自己画的widget确实实现了子线程里对pixmap画图,然后发给主线程,主线程paintevent直接调用drawpixmap。但如果要用你的方法,就要针对到所有用到的qt控件,qpushbutton, qwindow之类的都要自己实现双pixmap的更新机制,但这显然是不现实的。实际上我们的项目有很多很多菜单,用了很多qt自带的控件,当然也有我们自己代码画的qwidget控件。
Italink 2020-09-08
  • 打赏
  • 举报
回复
你应该是用的qPainter吧,你可以在子线程中使用QPainter对同一张QPixmap进行绘图,主线程去绘制这张qPixmap,需要注意的就是你显示这张pixmap的时机以及何时去清空这张pixmap,如果你不需要持续的实时绘制,你完全可以在主线程同时绘制这两个图形的pixmap,只不过如果某个pixmap如果没有绘制完成,你只需要给这张pixmap填充透明色,子线程绘图(或者重置)完毕,只需要发送一个信号,在主线程刷新一下界面即可
Italink 2020-09-08
  • 打赏
  • 举报
回复
基本大多数的GUI库都是只允许由主线程来操作UI吧。你可以在子线程中去处理帧缓存,主线程里只需要把你处理好的帧缓存显示到UI上
Italink 2020-09-08
  • 打赏
  • 举报
回复
如果你需要更高性能的绘图,可以学一下Qt封装的QOpenGLWidget,不过需要3D图形基础,短期内很难掌握
Italink 2020-09-08
  • 打赏
  • 举报
回复
我看你之前的回答,你说A需要0.01ms,B可能100ms,所以主线程可能40ms完成不了绘制导致卡顿,是因为你把大多事情都交给主线程了(比方说一些绘图的设置操作) 你需要做的是,主线程40ms定时刷新,每一次刷新都去绘制两张pixmap,不管这个pixmap里是什么。然后呢要做的就是在一个线程中以0.01ms去处理A对应的pixmap,以另一个线程以100ms来处理B对应的pixmap,这样就能保证主线程同步也不会出现卡顿
Italink 2020-09-08
  • 打赏
  • 举报
回复
40ms刷新的动画,帧数并不是很高,即便是你对整个屏幕进行一个实时的绘制也不会卡顿,占用都不会很高。也就是说单纯进行一个图形的绘制,没有太多处理,实时绘制是完全可以做到的。卡顿的原因你也清楚,是因为主线程的阻塞导致的。假设你这个主菜单对应A(pixmap),波形区域对应B,使用定时器去刷新界面,在主线程中只负责绘制这两个pixmap,也就是说主界面只能接触到这两个pixmap(从全局来看,你只是写了一个显示两张图片的窗口,而当下的计算机性能是很轻松就能完成的),而你要绘制波形区域,则是在子线程中对这个pixmap进行处理,处理频率可以由你自行设置,它不会导致主线程的阻塞
qq_21042359 2020-09-08
  • 打赏
  • 举报
回复
引用 9 楼 Italink 的回复:
你应该是用的qPainter吧,你可以在子线程中使用QPainter对同一张QPixmap进行绘图,主线程去绘制这张qPixmap,需要注意的就是你显示这张pixmap的时机以及何时去清空这张pixmap,如果你不需要持续的实时绘制,你完全可以在主线程同时绘制这两个图形的pixmap,只不过如果某个pixmap如果没有绘制完成,你只需要给这张pixmap填充透明色,子线程绘图(或者重置)完毕,只需要发送一个信号,在主线程刷新一下界面即可
谢谢回答,但我好像没看明白什么意思,是指波形区域用一个qpixmap吗?然后子线程对这个pixmap绘图。但是要眼睛看到这个pixmap,就要主线程真正调用drawpixmap把它画出来才能看到。那假设我定时器40ms去调用drawpixmap,但是假如这个时候弹出一个大菜单,主线程就会去画这个菜单,这个时候波形的drawpixmap就要等这个菜单画完并贴到屏幕上,因为它们都在一个线程上呀。这样子看起来就是波形会被卡了下。我是希望波形要像单片机中断一样,定时时间一到,强制画图,强制输出到framebuffer,眼睛必须看到波形被贴出来,效果是丝滑地、持续地走动。
龚建波 2020-09-04
  • 打赏
  • 举报
回复
又想把耗时的放ui,又想让ui快速刷新,找到了这种框架麻烦告诉我
qq_21042359 2020-09-04
  • 打赏
  • 举报
回复
这个不是什么数据填写和贴图分开这些基础问题。而是主线程正在被占用时并且CPU没有100% (毕竟如果100%,就没有讨论意义了),波形要继续贴出来,是贴出来,是能看到正在走动的贴出来。
qq_21042359 2020-09-04
  • 打赏
  • 举报
回复
引用 3 楼 芒果黑 的回复:
看一下QCoreApplication::processEvents()有没有用
这个应该用处不大,只要其他控件或者窗体正在主线程执行着超过40ms的事情,比如某个大窗口弹出时的paintevent,那么波形的paintevent就一定会等别人干完了,才轮到他,就算你把波形优先贴,但是别人事迟早都要干的,干的过程中,干多久,波形就要等多久才轮到,除非像单片机那样子中断嵌套。换句话说,这个问题我觉得没办法从事件循环角度去解决的。 抛开代码,总结就是只有1个线程,干A事和干B事,干A事每40ms就触发一次,只干0.000001ms,迅速解决,但是干B事呢,就有可能要100ms,那么干A事就会在B事来到并且正在干的时候,必须等待它干完,才轮到A事。所以我才说这是大难题,因为QT的UI是不允许子线程的,估计是为了安全。毕竟只有1个framebuffer,我们知道假如2个进程同时对1framebuffer写值,会发生什么事?那就是你的LCD屏会疯狂闪烁。
加载更多回复(4)

16,212

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧