我创建了一个基于Qt 5.2
的QML应用程序,我在Mac OS X和Windows(从XP到8)上部署。我的应用程序有一个主要动画,可以在用户直播时无限旋转图像。此动画是应用程序的核心部分,我无法将其删除。
旋转图像需要太多CPU能力,我正在寻找解决此问题的方法。其背后的原因是很多用户不支持OpenGL 2(在Windows上),我将不得不依靠MESA的DLL在软件中进行渲染,使得应用程序在这些机器上无法使用动画正在运行。
以下是我在QML中动画的当前实现:
Image {
id: imgBroadcastState
source: "images/broadcast_button.png"
anchors.horizontalCenter: parent.horizontalCenter
NumberAnimation on rotation {
from: 0
to: 360
running: rootWindow.isBroadcasting
loops: Animation.Infinite
duration: 7000
onRunningChanged:{
if(!running) {
imgBroadcastState.rotation = 0;
}
}
}
}
我尝试的第一个解决方案是创建一个包含动画的所有帧的巨大精灵,然后加载AnimatedSprite。这减少了CPU,但显然不够,RAM消耗增加了三倍以上,高达300MB,这对旧的Windows XP机器来说不是一个好的解决方案。
我还尝试了对QQuickPaintedItem进行子类化并每30ms手动调用paint()
(使用QTimer
)来旋转图像。这也会降低CPU,但也不够。这是我使用的代码:
void MXPaintedItem::paint(QPainter *painter)
{
QTransform rot;
rot.rotate(m_angle);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->translate(width() / 2, height() / 2);
painter->rotate(m_angle);
// Use preloaded QImage
painter->drawImage(QPoint(-width() / 2, -height() / 2), m_image);
m_angle += 2.5;
}
有没有办法改善这一点并降低旋转动画的CPU使用率?
修改:
当然我可以改变动画或不使用动画,但这不是一个长期的解决方案。最后,必须动态绘制/更新此图像以反映VUMeter并表示声级。因此,我需要找到一个合适的解决方案,允许我实时更新QML视图的一部分,而无需重绘整个UI并占用太多CPU。
EDIT2 :
我发现主CPU使用率不是轮换本身,而是每次都必须重绘整个UI的事实。您只需在return
函数中调用paint()
而不是旋转任何内容即可确保这一点。与动画图像本身相比,CPU使用情况相同,这表明问题来自每次更新场景中的一个QML组件时更新整个UI
答案 0 :(得分:0)
如果您有内存空间且旋转次数很小,请为每次旋转使用一个位图。这就是自计算机开始以来编写“旋转器”的方式。
理论上说,bitblit比执行旋转变换更快,然后blitting结果图像。
答案 1 :(得分:0)
接下来我会尝试拍摄动画并制作动画GIF。无论您使用什么工具生成gif,都应该能够配置压缩/优化以获得您满意的质量/尺寸。
然后尝试使用QML AnimatedImage Element来显示GIF,这可能会提供更好的结果。
答案 2 :(得分:0)
经过更多调查后,我得出的结论是,没有简单的方法来优化这一点。通过QML本身可以获得最佳性能,因为它针对缓存元素进行了优化,并改善了场景重新绘制。
主要解决方案是仅重绘场景的一部分。使用QML和新的SceneGraph渲染无法实现这一点,并且不会在不久的将来进行规划。这个答案是由Qt中负责开发此功能的人员给出的。
CPU使用率本身高度依赖于硬件和显卡驱动程序,因为现在所有内容都基于OpenGL 2.0,并且依赖于硬件/驱动程序正确支持某些OpenGL操作的事实。