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)
由于QML建立连接以在更改之间进行通信,因此会出现错误:
onStateChange通过PropertyChanges将不透明度更改为视图的不透明度属性进行连接。该onOpacityChanged信号将连接到State的when属性。该onWhenChanged信号将连接到state属性,从而进行绑定循环。
另一件事是,当您NumberAnimation在Transition中进行创建时,无需指定from和to属性。在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,并在加载组件时使用它来淡出。