MVD(四-形变的代理)

本文档展示了如何使用QtQuick的ListView组件和代理来创建一个可展开和收缩的链表项。每个链表项包含文字、图片,并在点击时扩展以显示详细信息,如评论文字。展开状态通过状态机和过渡动画实现,同时提供了关闭按钮。ListView的数据源由ListModel提供,代理负责渲染每个项,允许直接访问Model数据元素的属性。
摘要由CSDN通过智能技术生成
在下面的例子中,当点击链表项时,链表项都会展开填充整个链表视图 ListView )。
额外的间隔区域被用于添加更多的信息,这种机制使用一个 状态 控制
当一个链表项展开时,代理项都能输入 expanded (展开)状态,在这种状态 下一些属性被改变
 
 

需要注意的点:模型、视图、代理:

模型负责产生数据>>

// 链表视图数据来源
        ListModel {
            id: planets

            ListElement {
                name: "Picture1"
                imageSource: "qrc:/new/preImg/images/a.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture2"
                imageSource: "qrc:/new/preImg/images/b.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture3"
                imageSource: "qrc:/new/preImg/images/c.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture4"
                imageSource: "qrc:/new/preImg/images/d.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture5"
                imageSource: "qrc:/new/preImg/images/e.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture6"
                imageSource: "qrc:/new/preImg/images/f.jpg"
                facts: "there show some comment... "}
        }

视图负责组织数据>>

        // 链表视图
        ListView {
            id: listView
            anchors.fill: parent

            // 设置代理
            delegate: detailsDelegate

            // 设置数据来源
            model: planets
        }

这里祖师数据的方式就是 List 方式

代理负责渲染数据>>

        // 渲染 Item 的代理
        Component {
            id: detailsDelegate

            Item {
                // wrapper 就是链表视图的一项
                id: wrapper

                // 一个 item 的长和宽
                width: listView.width
                height: 30

                // item 左边显示的文字
                Rectangle {
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.top: parent.top

                    height: 30

                    color: "#FFB6C1"

                    Text {
                        anchors.left: parent.left
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.leftMargin: 4

                        font.pixelSize: parent.height-4
                        color: "white"

                        // 因为代理被(ListView)告知渲染(ListModel)的数据,
                        // 所以此代理可以直接访问 ListModel 数据元素的属性
                        text: name
                    }
                }

                // item 右边显示的小图片
                Rectangle {
                    id: image

                    width: 26
                    height: 26

                    anchors.right: parent.right
                    anchors.top: parent.top
                    anchors.rightMargin: 2
                    anchors.topMargin: 2

                    color: "#FFB6C1"

                    Image {
                        anchors.fill: parent
                        fillMode: Image.PreserveAspectFit
                        // 因为代理被(ListView)告知渲染(ListModel)的数据,
                        // 所以此代理可以直接访问 ListModel 数据元素的属性
                        source: imageSource
                    }
                }

                // 点击 item 切换到 item 展开状态
                MouseArea {
                    anchors.fill: parent
                    // 给当前的 item 输入 expanded
                    onClicked: parent.state = "expanded"
                }

                // 隐藏说明性文字
                Item {
                    id: factsView

                    // 将说明性文字隐藏在此 item 的下面,
                    // 范围是 item.bottom 到 屏幕底部
                    anchors.top: image.bottom
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.bottom: parent.bottom

                    // 完全透明
                    opacity: 0

                    // 放入文字
                    Rectangle {
                        anchors.fill: parent

                        // 渐变
                        gradient: Gradient {
                            GradientStop { position: 0.0; color: "#fed958" }
                            GradientStop { position: 1.0; color: "#fecc2f" }
                        }

                        Text {
                            anchors.fill: parent
                            anchors.margins: 5

                            clip: true
                            wrapMode: Text.WordWrap
                            color: "black"

                            font.pixelSize: 12

                            // 可以看到,只要是在代理的内部,
                            // 不论哪里都可以访问到 Model 数据元素的属性
                            text: facts
                        }
                    }
                }

                // 隐藏关闭按钮
                Rectangle {
                    id: closeButton

                    anchors.right: parent.right
                    anchors.top: parent.top
                    anchors.rightMargin: 2
                    anchors.topMargin: 2

                    width: 26
                    height: 26

                    color: "#DC143C"

                    // 透明
                    opacity: 0

                    MouseArea {
                        anchors.fill: parent
                        // 取消 item 的 expanded
                        onClicked: wrapper.state = ""
                    }
                }

                // 展开状态和默认状态之间的切换
                // 切换会在展开状态和默认状态之间切换
                states: [
                    State {
                        // 展开的状态的效果
                        name: "expanded"
                        // 当前 item 项布满整个屏幕
                        PropertyChanges {
                            target: wrapper
                            height: listView.height
                        }
                        // 将 item 原本右边的小图标布满整个屏幕
                        PropertyChanges {
                            target: image
                            width: listView.width
                            height: listView.width
                            anchors.rightMargin: 0
                            // 预留下30的高度用来显示说明性文字
                            anchors.topMargin: 30
                        }
                        // 本来隐藏的说明性文字让他显示
                        // 因为说明性文字本来在 item 没展开的时候
                        // 就隐藏在 item 的下面,这里在 item 的尺寸变大之后
                        // 取消文字的透明属性
                        PropertyChanges {
                            target: factsView
                            opacity: 1
                        }
                        // 关闭按钮从透明到显现
                        // 本来时候透明按钮隐藏在 item 的右面
                        PropertyChanges {
                            target: closeButton
                            opacity: 1
                        }
                        // 隐藏整个 List
                        // 用户看到的就一个展开之后的 item 布满整个屏幕
                        PropertyChanges {
                            target: wrapper.ListView.view
                            contentY: wrapper.y
                            // 设置视图的交互为false。
                            // 这个操作阻止了视图的移动,用户不再能够通过滚动条切换当前项
                            interactive: false
                        }
                    }
                ]

                // item 状态改变的过渡动画
                transitions: [
                    Transition {
                        NumberAnimation {
                            duration: 200;
                            properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY"
                        }
                    }
                ]
            }
        }

最重要的就是会写渲染,比如给这一项左边加文字、右边加图片、设置隐藏的文字在 item下边、设置 item 颜色、设置 item 点击动作、设置 item 状态切换、设置 item 状态切换的过渡动画等等!

这是一个数据项,视图将此数据项交给代理之后,代理怎么用数据项的属性,怎么渲染,那属于代理的任务!

完整代码:

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 800
    title: qsTr("Hello World")

    Item {
        anchors.fill: parent

        // 屏幕背景渐变
        Rectangle {
            anchors.fill: parent
            gradient: Gradient {
                GradientStop { position: 0.0; color: "#E6E6FA" }
                GradientStop { position: 1.0; color: "#E6E6FA" }
            }
        }

        // 链表视图
        ListView {
            id: listView
            anchors.fill: parent

            // 设置代理
            delegate: detailsDelegate

            // 设置数据来源
            model: planets
        }

        // 链表视图数据来源
        ListModel {
            id: planets

            ListElement {
                name: "Picture1"
                imageSource: "qrc:/new/preImg/images/a.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture2"
                imageSource: "qrc:/new/preImg/images/b.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture3"
                imageSource: "qrc:/new/preImg/images/c.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture4"
                imageSource: "qrc:/new/preImg/images/d.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture5"
                imageSource: "qrc:/new/preImg/images/e.jpg"
                facts: "there show some comment... "}
            ListElement {
                name: "Picture6"
                imageSource: "qrc:/new/preImg/images/f.jpg"
                facts: "there show some comment... "}
        }

        // 渲染 Item 的代理
        Component {
            id: detailsDelegate

            Item {
                // wrapper 就是链表视图的一项
                id: wrapper

                // 一个 item 的长和宽
                width: listView.width
                height: 30

                // item 左边显示的文字
                Rectangle {
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.top: parent.top

                    height: 30

                    color: "#FFB6C1"

                    Text {
                        anchors.left: parent.left
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.leftMargin: 4

                        font.pixelSize: parent.height-4
                        color: "white"

                        // 因为代理被(ListView)告知渲染(ListModel)的数据,
                        // 所以此代理可以直接访问 ListModel 数据元素的属性
                        text: name
                    }
                }

                // item 右边显示的小图片
                Rectangle {
                    id: image

                    width: 26
                    height: 26

                    anchors.right: parent.right
                    anchors.top: parent.top
                    anchors.rightMargin: 2
                    anchors.topMargin: 2

                    color: "#FFB6C1"

                    Image {
                        anchors.fill: parent
                        fillMode: Image.PreserveAspectFit
                        // 因为代理被(ListView)告知渲染(ListModel)的数据,
                        // 所以此代理可以直接访问 ListModel 数据元素的属性
                        source: imageSource
                    }
                }

                // 点击 item 切换到 item 展开状态
                MouseArea {
                    anchors.fill: parent
                    // 给当前的 item 输入 expanded
                    onClicked: parent.state = "expanded"
                }

                // 隐藏说明性文字
                Item {
                    id: factsView

                    // 将说明性文字隐藏在此 item 的下面,
                    // 范围是 item.bottom 到 屏幕底部
                    anchors.top: image.bottom
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.bottom: parent.bottom

                    // 完全透明
                    opacity: 0

                    // 放入文字
                    Rectangle {
                        anchors.fill: parent

                        // 渐变
                        gradient: Gradient {
                            GradientStop { position: 0.0; color: "#fed958" }
                            GradientStop { position: 1.0; color: "#fecc2f" }
                        }

                        Text {
                            anchors.fill: parent
                            anchors.margins: 5

                            clip: true
                            wrapMode: Text.WordWrap
                            color: "black"

                            font.pixelSize: 12

                            // 可以看到,只要是在代理的内部,
                            // 不论哪里都可以访问到 Model 数据元素的属性
                            text: facts
                        }
                    }
                }

                // 隐藏关闭按钮
                Rectangle {
                    id: closeButton

                    anchors.right: parent.right
                    anchors.top: parent.top
                    anchors.rightMargin: 2
                    anchors.topMargin: 2

                    width: 26
                    height: 26

                    color: "#DC143C"

                    // 透明
                    opacity: 0

                    MouseArea {
                        anchors.fill: parent
                        // 取消 item 的 expanded
                        onClicked: wrapper.state = ""
                    }
                }

                // 展开状态和默认状态之间的切换
                // 切换会在展开状态和默认状态之间切换
                states: [
                    State {
                        // 展开的状态的效果
                        name: "expanded"
                        // 当前 item 项布满整个屏幕
                        PropertyChanges {
                            target: wrapper
                            height: listView.height
                        }
                        // 将 item 原本右边的小图标布满整个屏幕
                        PropertyChanges {
                            target: image
                            width: listView.width
                            height: listView.width
                            anchors.rightMargin: 0
                            // 预留下30的高度用来显示说明性文字
                            anchors.topMargin: 30
                        }
                        // 本来隐藏的说明性文字让他显示
                        // 因为说明性文字本来在 item 没展开的时候
                        // 就隐藏在 item 的下面,这里在 item 的尺寸变大之后
                        // 取消文字的透明属性
                        PropertyChanges {
                            target: factsView
                            opacity: 1
                        }
                        // 关闭按钮从透明到显现
                        // 本来时候透明按钮隐藏在 item 的右面
                        PropertyChanges {
                            target: closeButton
                            opacity: 1
                        }
                        // 隐藏整个 List
                        // 用户看到的就一个展开之后的 item 布满整个屏幕
                        PropertyChanges {
                            target: wrapper.ListView.view
                            contentY: wrapper.y
                            // 设置视图的交互为false。
                            // 这个操作阻止了视图的移动,用户不再能够通过滚动条切换当前项
                            interactive: false
                        }
                    }
                ]

                // item 状态改变的过渡动画
                transitions: [
                    Transition {
                        NumberAnimation {
                            duration: 200;
                            properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY"
                        }
                    }
                ]
            }
        }
    }
}

运行>>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sssnial-jz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值