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)>>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值