QML components sequentially loading with fade
qml, qt, qt-quick, qt5, qtquick2
Solution
It gives you the error because QML make connections to communicate between changes:
`onStateChange` is connected by `PropertyChanges` that changes opacity to a view's opacity property. The `onOpacityChanged` signal will be connected to State's when property. The `onWhenChanged` signal will be connected to the state property, thus making binding Loop.
Another thing is that when you make `NumberAnimation` within Transition, you do not need to specify the `from` and `to` properties. The `PropertyChanges` sets the correct value.
Anyway, your states does not make sense, you using them wrong. You should also wait for fadeOut, because it will load so fast that you will not see the effect. Simply make two animations:
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
}
}
You should also change the loading to:
property int index: 0
onIndexChanged: { view.loadComponent(com_array[index]); }
But there is better solution: using `ShaderEffectSource` to take a frame of Loader before changing the source, and using it to fadeOut meanwhile loading the component.
Problem
I need sequentially to load one by one components from array. Before loading next component to Loader it should be fade-out , loaded and then fade-in. The code above blinks not correctly and show this message: "QML State: Binding loop detected for property "when" What have I done wrong? Thank you ``` 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]; } } ``` UPD Possible this could be useful for other, full example with correction ( thanks to answer author ): ``` 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 ); } } ```