【问题标题】:Huge flickering while main window height is animated主窗口高度动画时巨大的闪烁
【发布时间】:2019-09-12 23:44:11
【问题描述】:

在 Qt Quick 应用程序中,我想在单击切换按钮时为主窗口高度设置动画,以显示或隐藏一种托盘面板。主表单内容包含标题框架、滑动视图和下方的网格视图。

为了达到预期的效果,我在我的 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}
}

当我尝试打开托盘时,动画会在我的整个界面上造成巨大的闪烁。但是,当我关闭托盘时,动画完全没有闪烁,效果很流畅,正如我所料。

我的主窗口声明如下:

ApplicationWindow
{
    id: mainWindow
    visible: true
    width: 700
    height: 750
    color: "#000000"
    title: qsTr("Drag&Drop App")
    flags: Qt.Window | Qt.FramelessWindowHint

    ....

有人能解释一下为什么我会面临这样的闪烁吗?我应该改变什么来解决它?

【问题讨论】:

    标签: qt animation qml flicker qt-quick


    【解决方案1】:

    首先,我尝试使用一个小应用程序重现您的行为,如下所示:

    ma​​in.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();
    }
    

    ma​​in.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,闪烁消失了。闪烁的原因可能有很多,而这可能只是消除了一个原因。我已经经历过不合适的显卡驱动程序闪烁。您还应该考虑在不同的机器上运行您的程序。

    如果我的解决方案没有解决您的问题,请反馈。

    【讨论】:

    • 感谢您的回复,不幸的是这对我不起作用。这个问题实际上似乎广为人知(例如,我试图在 Google 上搜索“qt quick fix resize flickering”)。就好像每次都删除了背景,或者小部件没有双缓冲,因此指出了可能的配置问题。但是我尝试了几种我发现的解决方案,但没有一个对我有用。最奇怪的是,我用标准的 Qt Widgets 创建了完全相同的应用程序界面,而这个问题从未出现过。你对此有什么进一步的想法吗?
    • @Jean-MilostReymond:你试过我的程序吗?你有没有在另一台机器上试过我的程序?我很难帮助你,因为我在我的机器上重现了错误并且设置了窗口属性解决了这个问题。也许您可以尝试所有与 OpenGL 相关的应用程序属性。 doc.qt.io/qt-5/qt.html#ApplicationAttribute-enum
    • 是的,我尝试了您提到的应用程序,它在我的计算机上根本不闪烁,无论是否带有 AA_ShareOpenGLContexts 标志。我也在我的应用程序中玩过它们。我的窗口配置中应该缺少像双缓冲这样的标志,这是我能找到的唯一合乎逻辑的原因来解释为什么我的应用程序的内容会以这种方式闪烁。不幸的是,我花了几个小时在网上搜索,但没有成功。我只找到了这样的答案:stackoverflow.com/questions/30818886/…,但我真的不明白如何在我的案例中应用这样的解决方案......
    【解决方案2】:

    玩弄参数,终于找到了可以接受的方案。

    这是我注意到的:

    • 根据 Aleph0 的回复,我围绕着 OpenGL 标志进行了操作。我注意到使用Qt::ApplicationAttribute::AA_UseOpenGLES 标志完全解决了闪烁,但是在我的情况下它引起了一个奇怪的副作用:我的窗口中包含的所有组件的高度变得不一致,而主窗体的高度发生了变化,导致在动画,即使定义了正确的锚定和最小和最大高度约束。
    • 在我的主界面上,我删除了锚定并改为使用布局。这解决了高度变化期间奇怪的摆动,以及几乎所有的闪烁问题。我在具有不同操作系统的不同计算机上进行了测试,闪烁仅在几种特定情况下很少出现。
    • 但是,如果使用 OpenGLES,则在使用布局时仍会出现抖动。

    因此,在我的情况下,用布局替换锚点是解决方案,即使它并不完美。但至少结果是可以接受的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      • 2015-08-29
      • 2015-01-31
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      相关资源
      最近更新 更多