QML间接连接(Connecting Indirectly)和间接绑定(Binding Indirectly)
间接连接(Connecting Indirectly)
间接连接允许我们在运行时更改Connections的target.
使用QML时, 有时需要在运行时, 监控不同的对象的信号. 可采用以下方法动态更改Connections的target属性实现.
代码如下
Rectangle {
id: container
width: 600
height: 400
color: "white"
//左侧两个矩形布局
Column {
anchors.top: parent.top
anchors.left: parent.left
spacing: 20
Rectangle {
width: 290
height: 50
color: "lightGray"
MouseArea {
anchors.fill: parent
onClicked: container.state = "left"
}
Text {
anchors.centerIn: parent
font.pixelSize: 30
text: container.state==="left"?"Active":"inactive";
}
}
// M1>>
Rectangle {
id: leftRectangle
width: 290
height: 200
color: "green"
MouseArea {
id: leftMouseArea
anchors.fill: parent
onClicked: leftClickedAnimation.start();
}
Text {
anchors.centerIn: parent
font.pixelSize: 30
color: "white"
text: "Click me!"
}
}
// <<M1
}
//右侧两个矩形布局
Column {
anchors.top: parent.top
anchors.right: parent.right
spacing: 20
Rectangle {
width: 290
height: 50
color: "lightGray"
MouseArea {
anchors.fill: parent
onClicked: container.state = "right"
}
Text {
anchors.centerIn: parent
font.pixelSize: 30
text: container.state==="right"?"Active":"inactive";
}
}
Rectangle {
id: rightRectangle
width: 290
height: 200
color: "blue"
MouseArea {
id: rightMouseArea
anchors.fill: parent
onClicked: rightClickedAnimation.start();
}
Text {
anchors.centerIn: parent
font.pixelSize: 30
color: "white"
text: "Click me!"
}
}
}
//下方字体
Text {
id: activeText
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 50
font.pixelSize: 30
color: "red"
text: "Active area clicked!"
opacity: 0
}
//左侧矩形由白变绿动画
SequentialAnimation {
id: leftClickedAnimation
PropertyAction {
target: leftRectangle
property: "color"
value: "white"
}
ColorAnimation {
target: leftRectangle
property: "color"
to: "green"
duration: 3000
}
}
//右侧矩形从白变蓝动画
SequentialAnimation {
id: rightClickedAnimation
PropertyAction {
target: rightRectangle
property: "color"
value: "white"
}
ColorAnimation {
target: rightRectangle
property: "color"
to: "blue"
duration: 3000
}
}
//下方字体从完全透明变到不透明动画
SequentialAnimation {
id: activeClickedAnimation
PropertyAction {
target: activeText
property: "opacity"
value: 1
}
PropertyAnimation {
target: activeText
property: "opacity"
to: 0
duration: 3000
}
}
// M2>>
Connections {
id: connections
target: rightMouseArea
onClicked: activeClickedAnimation.start();
}
// <<M2
// M3>>
states: [
State {
name: "left"
StateChangeScript {
script: connections.target = leftMouseArea
}
},
State {
name: "right"
StateChangeScript {
script: connections.target = rightMouseArea
}
}
]
// <<M3
Component.onCompleted: {
state = "left";
}
}
可以看到Connections中本来连接的是右侧矩形的点击区域, 但在Component.onCompleted中, 我们使用State(注意也只能使用State)修改了Connections的target属性, 将其target修改为左侧矩形的点击区域. 最终效果如下(下侧文字动画链接到了左侧点击区域):
间接绑定(Binding Indirectly)
有时我们需要运行时根据实际情况来绑定不同的target的某项属性, 可以使用Binding来实现间接绑定.
代码如下:
Rectangle {
id: root
width: 600
height: 400
property int speed: 0 //参数speed
SequentialAnimation {
running: true
loops: Animation.Infinite
NumberAnimation { target: root; property: "speed"; to: 145; easing.type: Easing.InOutQuad; duration: 4000; }
NumberAnimation { target: root; property: "speed"; to: 10; easing.type: Easing.InOutQuad; duration: 2000; }
}
// M1>>
Loader {
id: dialLoader
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: analogButton.top
onLoaded: {
binder.target = dialLoader.item; //根据Loader加载的对象不同, 将binder的target对象进行指定
}
}
Binding {
id: binder
//target在此时是未知的, 且这里会报not defined错误, 但不影响运行. 也可以指定一个有效的target以避免语法错误提示, 但这不是必要的.
property: "speed" //绑定target的speed属性
value: speed //值从参数speed获取(参数speed的值会赋给target.speed属性, 从而影响target的显示).
}
// <<M1
//左下方按钮
Rectangle {
id: analogButton
anchors.left: parent.left
anchors.bottom: parent.bottom
color: "gray"
width: parent.width/2
height: 100
Text {
anchors.centerIn: parent
text: "Analog"
}
MouseArea {
anchors.fill: parent
onClicked: root.state = "analog";
}
}
//右下方按钮
Rectangle {
id: digitalButton
anchors.right: parent.right
anchors.bottom: parent.bottom
color: "gray"
width: parent.width/2
height: 100
Text {
anchors.centerIn: parent
text: "Digital"
}
MouseArea {
anchors.fill: parent
onClicked: root.state = "digital";
}
}
state: "analog"
// M3>>
//状态
states: [
State {
name: "analog"
PropertyChanges { target: analogButton; color: "green"; } //左侧按钮变绿
PropertyChanges { target: dialLoader; source: "Analog.qml"; } //加载QML界面
},
State {
name: "digital"
PropertyChanges { target: digitalButton; color: "green"; } //右侧按钮变绿
PropertyChanges { target: dialLoader; source: "Digital.qml"; } //加载QML界面
}
]
// <<M3
}
代码运行效果如下:
其他技巧
绑定的破坏与恢复
- 赋值会破坏绑定, 如果要恢复绑定可以调用Qt.binding, 代码如下:
Button {
onClicked: {
item2.value = item1.value1 + 1 //这个是赋值表达式, 会破坏绑定
item2.value = Qt.binding(function() { return item1.value1 + 1;}) //这个是绑定
}
}
- 也可以使用Binding的条件绑定来控制绑定的破坏和恢复, 代码如下:
property bool needBind: true
Binding {
target: item2
property: "value2"
value: item1.value1 + 1
when: needBind
}
Button {
onClicked: {
needBind = false; //绑定破坏
item2.value = item1.value1 + 10;
}
}
Button {
onClicked: {
needBind = true; //绑定恢复
}
}
以上代码摘录自: <<QML book (ch14)>>