动画主要 window 高度时出现巨大的闪烁
Huge flickering while main window height is animated
在 Qt Quick 应用程序中,我想在单击切换按钮时为主要 window 高度设置动画,以便显示或隐藏一种托盘面板。主表单内容包含一个 header 框架、一个滑动视图和一个网格视图。
为了达到预期的效果,我在我的 qss 代码中添加了以下动画,根据我的切换按钮状态,它们是 运行:
ParallelAnimation
{
id: one_dev_connected_toggle_window_height_increase
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 750; easing.type: Easing.InOutQuad; duration: 500}
}
ParallelAnimation
{
id: one_dev_connected_toggle_window_height_decrease
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 450; easing.type: Easing.InOutQuad; duration: 500}
}
当我尝试打开托盘时,动画导致我的整个界面出现巨大的闪烁。但是,当我关闭托盘时,动画完全没有闪烁,效果很流畅,正如我所料。
我的主要 window 声明如下:
ApplicationWindow
{
id: mainWindow
visible: true
width: 700
height: 750
color: "#000000"
title: qsTr("Drag&Drop App")
flags: Qt.Window | Qt.FramelessWindowHint
....
有人能解释一下为什么我会遇到这样的闪烁吗?我应该更改什么来修复它?
首先,我尝试使用下面列出的小应用程序重现您的行为:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
// Adding the following line helps to remove the flickering
app.setAttribute(Qt::ApplicationAttribute::AA_ShareOpenGLContexts, true);
engine.load(QUrl("./data/main.qml"));
return app.exec();
}
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.5
ApplicationWindow {
id: mainWindow
width: 800; height: 1000
title: "Animation Flickers"
visible: true
property bool large:true
MouseArea {
anchors.fill: parent
onClicked: {
if (mainWindow.large) {
decr.start()
} else {
incr.start();
}
mainWindow.large=!mainWindow.large;
}
}
ParallelAnimation
{
id: incr
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 750; easing.type: Easing.InOutQuad; duration: 500}
}
ParallelAnimation
{
id: decr
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 450; easing.type: Easing.InOutQuad; duration: 500}
}
}
然后我激活了应用程序属性AA_ShareOpenGLContexts
,闪烁消失了。闪烁的原因可能有很多,这可能只是消除了一个原因。我已经经历过不合适的显卡驱动程序的闪烁。您还应该考虑 运行 您的程序在另一台机器上。
如果我的解决方案没有解决您的问题,请反馈。
把玩参数,我终于找到了一个可以接受的解决方案。
这是我注意到的:
- 根据 Aleph0 的回复,我开始研究 OpenGL 标志。我注意到使用
Qt::ApplicationAttribute::AA_UseOpenGLES
标志完全解决了闪烁问题,但是它在我的例子中造成了一个奇怪的副作用:我的 window 中包含的所有组件的高度变得不一致,而主窗体高度发生了变化,导致动画过程中的一种摆动,即使定义了正确的锚定和最小和最大高度约束。
- 在我的主界面上,我删除了锚点并改用了布局。这解决了高度变化期间奇怪的摇晃,以及几乎所有的闪烁问题。我在不同 OS 的不同计算机上进行了测试,在某些特定情况下闪烁很少出现。
- 但是,如果使用 OpenGLES,则在使用布局时仍然会出现抖动。
所以在我的案例中,用布局替换锚点是解决方案,即使它工作得不完美。但至少结果是可以接受的。
在 Qt Quick 应用程序中,我想在单击切换按钮时为主要 window 高度设置动画,以便显示或隐藏一种托盘面板。主表单内容包含一个 header 框架、一个滑动视图和一个网格视图。
为了达到预期的效果,我在我的 qss 代码中添加了以下动画,根据我的切换按钮状态,它们是 运行:
ParallelAnimation
{
id: one_dev_connected_toggle_window_height_increase
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 750; easing.type: Easing.InOutQuad; duration: 500}
}
ParallelAnimation
{
id: one_dev_connected_toggle_window_height_decrease
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 450; easing.type: Easing.InOutQuad; duration: 500}
}
当我尝试打开托盘时,动画导致我的整个界面出现巨大的闪烁。但是,当我关闭托盘时,动画完全没有闪烁,效果很流畅,正如我所料。
我的主要 window 声明如下:
ApplicationWindow
{
id: mainWindow
visible: true
width: 700
height: 750
color: "#000000"
title: qsTr("Drag&Drop App")
flags: Qt.Window | Qt.FramelessWindowHint
....
有人能解释一下为什么我会遇到这样的闪烁吗?我应该更改什么来修复它?
首先,我尝试使用下面列出的小应用程序重现您的行为:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
// Adding the following line helps to remove the flickering
app.setAttribute(Qt::ApplicationAttribute::AA_ShareOpenGLContexts, true);
engine.load(QUrl("./data/main.qml"));
return app.exec();
}
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.5
ApplicationWindow {
id: mainWindow
width: 800; height: 1000
title: "Animation Flickers"
visible: true
property bool large:true
MouseArea {
anchors.fill: parent
onClicked: {
if (mainWindow.large) {
decr.start()
} else {
incr.start();
}
mainWindow.large=!mainWindow.large;
}
}
ParallelAnimation
{
id: incr
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 750; easing.type: Easing.InOutQuad; duration: 500}
}
ParallelAnimation
{
id: decr
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 450; easing.type: Easing.InOutQuad; duration: 500}
}
}
然后我激活了应用程序属性AA_ShareOpenGLContexts
,闪烁消失了。闪烁的原因可能有很多,这可能只是消除了一个原因。我已经经历过不合适的显卡驱动程序的闪烁。您还应该考虑 运行 您的程序在另一台机器上。
如果我的解决方案没有解决您的问题,请反馈。
把玩参数,我终于找到了一个可以接受的解决方案。
这是我注意到的:
- 根据 Aleph0 的回复,我开始研究 OpenGL 标志。我注意到使用
Qt::ApplicationAttribute::AA_UseOpenGLES
标志完全解决了闪烁问题,但是它在我的例子中造成了一个奇怪的副作用:我的 window 中包含的所有组件的高度变得不一致,而主窗体高度发生了变化,导致动画过程中的一种摆动,即使定义了正确的锚定和最小和最大高度约束。 - 在我的主界面上,我删除了锚点并改用了布局。这解决了高度变化期间奇怪的摇晃,以及几乎所有的闪烁问题。我在不同 OS 的不同计算机上进行了测试,在某些特定情况下闪烁很少出现。
- 但是,如果使用 OpenGLES,则在使用布局时仍然会出现抖动。
所以在我的案例中,用布局替换锚点是解决方案,即使它工作得不完美。但至少结果是可以接受的。