Qml 模型-视图-代理(贰)之 代理(Delegate) 学习

使用模型与视图来定义用户界面时,代理在创建显示时扮演了大量的角色,在模型中的每个元素通过代理来实现可视化。 

代理

使用键盘移动 高亮 效果 

代码: 

视图绑定的属性是 ListView.isCurrentItem: 这个属性是一个布尔值,标识这个元素是否是 视图的当前元素,也就是否当前元素获取到 焦点。

每个代理的width(宽度)属性与视图的width(宽度)属性绑定,每个代理的背景颜色color 依赖绑定的属性ListView.isCurrentItem 属性。

动画添加与移除元素(Animating Added and Removed Items)

动画添加与移除效果

QML 视图为每个代理绑定了两个信号,onAdd和onRemove 。使用动画连接它们。使⽤动画连接它们,可以⽅便创建识别哪些内容被添加或删除 的动画。

动态填充一个链表模型(ListModel)

调用模型的 append 方法来添加一个新的元素,点击添加操作会 触发视图创建⼀个新的代理,并发送 GridView.onAdd信号。SequentialAnimation队列动画与这个信号连接绑定, 使⽤代理的scale属性来放⼤视图元素。

当视图中的⼀个代理点击时,将会调⽤模型的remove⽅法将⼀个元素从模型
中移除。
import QtQuick 2.15

Rectangle{
    width: 200
    height: 300

    color: "white"

    // ListView{
    //     anchors.fill: parent
    //     anchors.margins: 20
    //     model: 100

    //     clip: true
    //     delegate: numberDelegateTest

    //     spacing: 5
    //     focus: true

    // }
    // Component{
    //     id: numberDelegateTest

    //     Rectangle{
    //         width: ListView.view.width
    //         height: 40

    //         color: ListView.isCurrentItem ? "gray" : "lightGreen"

    //         Text {
    //             anchors.centerIn: parent
    //             font.pixelSize: 20
    //             text: index
    //         }

    //     }

    // }








    ListModel{
        id: theListModel
        ListElement{
            number:0
        }
        ListElement{
            number:1
        }
        ListElement{
            number:2
        }
        ListElement{
            number:3
        }
        ListElement{
            number:4
        }
        ListElement{
            number:5
        }
        ListElement{
            number:6
        }
        ListElement{
            number:7
        }
        ListElement{
            number:8
        }
    }

    Rectangle{
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.margins: 20

        height: 40

        color: "darkGreen"

        Text {
            anchors.centerIn: parent
            text: "add Item!"
        }
        MouseArea{
            //parent是当前对外象外的 也就是当前花括号外面的对象
            anchors.fill: parent
            onClicked: {
                theListModel.append({"number": ++parent.count})
            }
        }
        property int count: 9
    }


    GridView{
        anchors.fill: parent
        anchors.margins: 20
        anchors.bottomMargin: 80

        clip: true

        model: theListModel

        cellWidth: 45
        cellHeight: 45

        delegate: numberDelegateTest2


    }

    Component{
        id: numberDelegateTest2
        Rectangle{
            id:wrapperTest
            width: 40
            height: 40
            color: "lightGreen"
            Text{
                anchors.centerIn: parent
                font.pixelSize: 10
                text: number

            }

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    if(!wrapperTest.GridView.delayRemove)
                        theListModel.remove(index)
                }
            }

            GridView.onRemove: SequentialAnimation {
                PropertyAction { target: wrapperTest; property: "GridView.delayRemove"; value: true }
                NumberAnimation { target: wrapperTest; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
                PropertyAction { target: wrapperTest; property: "GridView.delayRemove"; value: false }

            }
            GridView.onAdd: SequentialAnimation {
                NumberAnimation { target: wrapperTest; property: "scale"; from: 0; to: 1; duration: 250; easing.type: Easing.InOutQuad }

            }
        }
    }
}

形变的代理

通常使用链表时会使用当前项激活时展开的机制,这个操作可以被用于动态的 将当前项目填充到整个屏幕 来 添加一个新的用户界面, 或者为链表中的当前项提供更多的信息。
点击链表时,链表项会展开填充整个链表视图(ListView)。额外的区域用于添加更多的信息,这种机制使用一个状态来控制,当一个链表项展开时,代理项都能输入 expanded 展开状态,在这种状态下一些属性被改变。

包装器(wrapper)的高度(height)被设置为链表视图(ListView)的高度。标签图片被放大并且下移,使图片 从小图片的位置 大图片的位置移动。 两个隐藏项, 实际视图(factsView)与 关闭按键(closeButton)切换它的 透明度(opacity 属性) 显示出来。

设置链表视图(ListView)包含了设置内容Y坐标(constemtsY)这是视图顶部可见的部分代理的 Y轴坐标。 另一个变化是设置视图的交互(interactive)为false。 这个操作阻止了视图的移动,用户不能动条切换当前项。

效果图:

左侧文本标题

文本取Model 中的子项 ListElement 中属性 名称(name)

右侧图片

图片源为  ListElement 中属性 名称(imageSource)

说明文本视图

文本内容也是ListElement 中属性 facts

关闭按钮

点击事件

状态

动画

完整代码

import QtQuick 2.15

Rectangle{
    width: 1600
    height: 600

    color: "white"

    // ListView{
    //     anchors.fill: parent
    //     anchors.margins: 20
    //     model: 100

    //     clip: true
    //     delegate: numberDelegateTest

    //     spacing: 5
    //     focus: true

    // }
    // Component{
    //     id: numberDelegateTest

    //     Rectangle{
    //         width: ListView.view.width
    //         height: 40

    //         color: ListView.isCurrentItem ? "gray" : "lightGray"

    //         Text {
    //             anchors.centerIn: parent
    //             font.pixelSize: 20
    //             text: index
    //         }

    //     }

    // }








    // ListModel{
    //     id: theListModel
    //     ListElement{
    //         number:0
    //     }
    //     ListElement{
    //         number:1
    //     }
    //     ListElement{
    //         number:2
    //     }
    //     ListElement{
    //         number:3
    //     }
    //     ListElement{
    //         number:4
    //     }
    //     ListElement{
    //         number:5
    //     }
    //     ListElement{
    //         number:6
    //     }
    //     ListElement{
    //         number:7
    //     }
    //     ListElement{
    //         number:8
    //     }
    // }

    // Rectangle{
    //     anchors.left: parent.left
    //     anchors.right: parent.right
    //     anchors.bottom: parent.bottom
    //     anchors.margins: 20

    //     height: 40

    //     color: "darkGreen"

    //     Text {
    //         anchors.centerIn: parent
    //         text: "add Item!"
    //     }
    //     MouseArea{
    //         //parent是当前对外象外的 也就是当前花括号外面的对象
    //         anchors.fill: parent
    //         onClicked: {
    //             theListModel.append({"number": ++parent.count})
    //         }
    //     }
    //     property int count: 9
    // }


    // GridView{
    //     anchors.fill: parent
    //     anchors.margins: 20
    //     anchors.bottomMargin: 80

    //     clip: true

    //     model: theListModel

    //     cellWidth: 45
    //     cellHeight: 45

    //     delegate: numberDelegateTest2


    // }

    // Component{
    //     id: numberDelegateTest2
    //     Rectangle{
    //         id:wrapperTest
    //         width: 40
    //         height: 40
    //         color: "lightGreen"
    //         Text{
    //             anchors.centerIn: parent
    //             font.pixelSize: 10
    //             text: number

    //         }

    //         MouseArea{
    //             anchors.fill: parent
    //             onClicked: {
    //                 if(!wrapperTest.GridView.delayRemove)
    //                     theListModel.remove(index)
    //             }
    //         }

    //         GridView.onRemove: SequentialAnimation {
    //             PropertyAction { target: wrapperTest; property: "GridView.delayRemove"; value: true }
    //             NumberAnimation { target: wrapperTest; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
    //             PropertyAction { target: wrapperTest; property: "GridView.delayRemove"; value: false }

    //         }
    //         GridView.onAdd: SequentialAnimation {
    //             NumberAnimation { target: wrapperTest; property: "scale"; from: 0; to: 1; duration: 250; easing.type: Easing.InOutQuad }

    //         }
    //     }
    // }






    ListView{
        id: listViewTest
        anchors.fill: parent
        delegate: detailsDelegate
        model: planets

    }


    ListModel
    {
        id: planets
        ListElement { name: "Mercury"; imageSource: "ufo.jpg"; facts: "Mercury is the smallest planet in the Solar System. It is the closest planet to the sun. It makes one trip around the Sun once every 87.969 days." }
        ListElement { name: "Venus"; imageSource: "SiC.jpeg"; facts: "Venus is the second planet from the Sun. It is a terrestrial planet because it has a solid, rocky surface. The other terrestrial planets are Mercury, Earth and Mars. Astronomers have known Venus for thousands of years." }
        ListElement { name: "Earth"; imageSource: "football1.jpeg"; facts: "The Earth is the third planet from the Sun. It is one of the four terrestrial planets in our Solar System. This means most of its mass is solid. The other three are Mercury, Venus and Mars. The Earth is also called the Blue Planet, 'Planet Earth', and 'Terra'." }
        ListElement { name: "Mars"; imageSource: "football.jpg"; facts: "Mars is the fourth planet from the Sun in the Solar System. Mars is dry, rocky and cold. It is home to the largest volcano in the Solar System. Mars is named after the mythological Roman god of war because it is a red planet, which signifies the colour of blood." }
    }

    Component{
        id: detailsDelegate
        Item {
            id: wrapper
            width: listViewTest.width
            height: 30
            Rectangle{
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: parent.top

                height: 30

                color: "#ffaa00"

                Text {
                    anchors.left: parent.left
                    anchors.verticalCenter: parent.verticalCenter
                    font.pixelSize: parent.height-4
                    text: name
                }
            }

            Rectangle{
                id: imageTest
                color: "black"
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.rightMargin: 2
                anchors.topMargin: 2
                width: 26
                height: 26
                Image {
                    anchors.fill: parent
                    fillMode: Image.PreserveAspectFit
                    source: imageSource
                }
            }

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    parent.state = "expanded"
                    console.log(name + "被点击")
                }
            }

            Item {
                id: factsView
                anchors.top: imageTest.bottom
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.bottom: parent.bottom

                opacity: 0

                Rectangle{
                    anchors.fill: parent
                    color: "#cccccc"

                    Text {
                        anchors.fill: parent
                        anchors.margins: 5
                        clip: true
                        wrapMode: Text.WordWrap
                        font.pixelSize: 12
                        text: facts
                    }
                }
            }

            Rectangle
            {
                id: closeButton
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.rightMargin: 2
                anchors.topMargin: 2
                width: 26

                height: 26
                color: "red"
                opacity: 0
                MouseArea {
                        anchors.fill: parent
                        onClicked: wrapper.state = ""
                }
                Text{
                    anchors.fill: parent
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.verticalCenter: parent.verticalCenter
                    font.pixelSize: 26
                    text: "X"
                }
            }

            states:
                [
                State {
                    name: "expanded"
                    PropertyChanges { target: wrapper; height: listViewTest.height }
                    PropertyChanges { target: imageTest; width: listViewTest.width; height: listViewTest.height -200; anchors.rightMargin: 0; anchors.topMargin: 30 }
                    PropertyChanges { target: factsView; opacity: 1 }
                    PropertyChanges { target: closeButton; opacity: 1 }
                    PropertyChanges { target: wrapper.ListView.view; contentY: wrapper.y; interactive: false }
                }
            ]

            transitions: [
                Transition {
                    NumberAnimation {
                        duration: 200;
                        properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY"

                    }

                }
            ]
        }
    }

}

遇到的问题

  • 点击没反应 expanded 状态拼写错误 导致状态切换不了
  • 图片设置高度不对 导致文本不显示

  • 包装状态切换被注释导致 显示有问题  导致切换条目显示不到图片下面 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值