Qt踩坑记录
1.QCustom3DLabel更新显示文本
环境: Qt5.14.2,mingW,Windows10
场景: 在Q3DScatter中添加大量QCustom3DLabel对象,并实时更新所有对象的显示值
实施方案一: 在添加QCustom3DLabel对象到Q3DScatter中时,同步缓存指针(或每次从Q3DScatter取出所有QCustom3DLabel对象),再调用QCustom3DLabel的接口 void setText(const QString &text) 逐个更新。
存在的问题: 每个耗时约0.5ms(debug版本测试),如果需要更新的QCustom3DLabel对象较多,容易出现卡顿。如果数量多的情况下,更新频率很快,资源将全部用于更新显示,导致软件卡死。
实施方案二: 提前将需要显示的所有文本,绘制到QImage中进行保存(图片背景填充为透明)。更新显示文本时,先从缓存的图片中找到显示文本的对应图片,再调用QCustom3DLabel的父类QCustom3DItem接口void setTextureImage(const QImage &textureImage)来更新纹理(需要禁用边框)。
存在的问题:
- 如果像实施方案一一样采用缓存QCustom3DLabel对象,则更新图片纹理无效(仅第一次设置图片纹理有效,后续更新后还是显示第一次设置的图片)。
- 如果在每次更新时,通过Q3DScatter的接口removeCustomItem移除指定的QCustom3DLabel,再重新创建新的QCustom3DLabel对象,设置属性和更新图片纹理后,重新添加到Q3DScatter中。当需要更新的QCustom3DLabel对象数量较少时(测试少于20个),可以正常更新显示。当对象数量较多时,将出现部分更新失败,还是显示第一次设置的图片纹理,经打印对象地址,发现更新失败的QCustom3DLabel对象,虽然是通过new重新创建的,但是其地址和被removeCustomItem移除的QCustom3DLabel对象地址相同,由此推测是Q3DScatter内部做了缓存,没有更新重新创建的对象进去。
- 如果在每次removeCustomItem接口之后,调用QCoreApplication::processEvents()接口执行事件循环,可以确保removeCustomItem真正的移除指定的QCustom3DLabel对象,即再数量较多时,依然能够每次都更新成功图片纹理。但是,执行事件循环的耗时,导致整个更新过程延长,导致更新卡顿,如果更新频率较快,则将导致软件卡死。
结论: 在5.14.2的版本上,QCustom3DLabel无法满足大批量的文本更新显示。QCustom3DItem的图片纹理更新机制存在问题,数量较多时将更新失败。