动画主要 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,则在使用布局时仍然会出现抖动。

所以在我的案例中,用布局替换锚点是解决方案,即使它工作得不完美。但至少结果是可以接受的。