QML组件以淡入淡出顺序加载

Dmi*_*try 3 qt qml qt-quick qt5 qtquick2

我需要按顺序从数组中加载一个组件。在将下一个组件加载到Loader之前,应先淡出,加载然后淡入。

上面的代码未正确闪烁,并显示以下消息:“ QML状态:为属性” when“检测到绑定循环

我做错了什么?

谢谢

import QtQuick 2.0

Rectangle {
    id: screen
    width: 400
    height: 400
    color: "black"

    Rectangle {
        id: view
        anchors.fill: parent

        Loader {
            id: loader
            onLoaded: { view.state="fadeIn"; }
        }

        states: [
            State {
                name: "fadeOut";
                PropertyChanges { target: view; opacity: 0.1; }
            },
            State {
                name: "fadeIn";
                PropertyChanges { target: view; opacity: 1; }
            },
            State {
                name: "load"; when: view.opacity == 0;
                StateChangeScript { script: { loader.sourceComponent=com_array[index]; } }
            }
        ]

        transitions: [
            Transition {
                to: "fadeIn"
                NumberAnimation { properties: "opacity"; from: 0.0; to: 0.99; duration: 2000 }
            },
            Transition {
                to: "fadeOut"
                NumberAnimation { properties: "opacity"; from: 0.99; to: 0; duration: 2000 }
            }
        ]
    }

    Timer {
        id: timer

        interval: 3000; running: true; repeat: true
        onTriggered:  {
            ++index;
            if( index >= com_array.length ) {
                index = 0
            }

            view.state="fadeOut"
        }
    }

    // -------------------------------------------------------------------
    // Components

    Item {
        id: list

        property Component red_rect_com : Component {
            Rectangle {
                width: screen.width; height: screen.height

                Rectangle {
                    anchors.fill: parent; color: "red";
                }
            }
        }

        property Component blue_rect_com : Component {
            Rectangle {
                width: screen.width; height: screen.height

                Rectangle {
                    anchors.fill: parent; color: "blue";
                }
            }
        }
    }

    property int index: 0
    property var com_array: [ list.red_rect_com, list.blue_rect_com ]
    Component.onCompleted: { loader.sourceComponent = com_array[index]; }
}
Run Code Online (Sandbox Code Playgroud)

UPD

可能这对于其他更正的完整示例很有用(感谢答案作者):

import QtQuick 2.0

Rectangle {
    id: screen
    width: 400
    height: 400
    color: "black"

    Rectangle {
        id: view
        anchors.fill: parent
        property var sourceComponent
        opacity: 0

        function loadComponent( component, is_first_start ) {
            sourceComponent = component;

            if( is_first_start ) {
                fadeOut.stop(); fadeIn.start();
            }
            else {
                fadeIn.stop(); fadeOut.start();
            }
        }

        Loader {
            id: loader
            onLoaded: {
                fadeOut.stop();
                fadeIn.start();
            }
        }

        NumberAnimation on opacity {
            id: fadeOut;
            to: 0.0;
            duration: 2000;
            onStopped: { loader.sourceComponent=view.sourceComponent; }
        }

        NumberAnimation on opacity {
            id: fadeIn;
            to: 1.0;
            duration: 2000
        }
    }

    Timer {
        id: timer

        interval: 4000; running: true; repeat: true
        onTriggered: {
            ++index;
            if( index >= com_array.length ) {
                index = 0
            }

            view.loadComponent( com_array[index], false );
        }
    }

    // -------------------------------------------------------------------
    // Components

    Item {
        id: list

        property Component red_rect_com : Component {
            Rectangle {
                width: screen.width; height: screen.height

                Rectangle {
                    anchors.fill: parent; color: "red";
                }
            }
        }

        property Component blue_rect_com : Component {
            Rectangle {
                width: screen.width; height: screen.height

                Rectangle {
                    anchors.fill: parent; color: "blue";
                }
            }
        }
    }

    property int index: 0
    property var com_array: [ list.red_rect_com, list.blue_rect_com ]
    Component.onCompleted: { view.loadComponent( com_array[index], true ); }
}
Run Code Online (Sandbox Code Playgroud)

Arp*_*ius 5

由于QML建立连接以在更改之间进行通信,因此会出现错误:

onStateChange通过PropertyChanges将不透明度更改为视图的不透明度属性进行连接。该onOpacityChanged信号将连接到State的when属性。该onWhenChanged信号将连接到state属性,从而进行绑定循环。

另一件事是,当您NumberAnimation在Transition中进行创建时,无需指定fromto属性。在PropertyChanges设定正确的值。

无论如何,您的状态没有意义,您使用它们是错误的。您还应该等待fadeOut,因为它将很快加载,以至于看不到效果。只需制作两个动画:

Rectangle {
    id: view
    anchors.fill: parent
    property var sourceComponent
    function loadComponent(component){
        fadeIn.stop(); fadeOut.start();
        sourceComponent = component;
    }
    Loader {
        id: loader
        onLoaded: { fadeOut.stop(); fadeIn.start(); }
    }
    NumberAnimation on opacity {
        id: fadeOut
        to: 0.0
        onStopped: { loader.sourceComponent= sourceComponent; }
    }
    NumberAnimation on opacity {
        id: fadeIn
        to: 1.0
    }
}
Run Code Online (Sandbox Code Playgroud)

您还应该将加载更改为:

property int index: 0
onIndexChanged:  { view.loadComponent(com_array[index]); }
Run Code Online (Sandbox Code Playgroud)

但是有更好的解决方案:ShaderEffectSource用于在更改源之前拍摄一帧Loader,并在加载组件时使用它来淡出。