QtQuick 中的模型视图代理

68 篇文章 24 订阅
23 篇文章 1 订阅
QtQuick 中的模型视图代理
//对于开发用户界面,最重要的一方面是保持数据与可视化的分离。
//在QML中,model与view通过delegate连接起来。model提供数据,对于每个数据项,可能有多个值;显示在view中
//的每项数据都是通过代理来实现可视化;view的任务是排列这些delegate.
* 最基本的分离数据与显示的方法是使用Repeater元素,它被用于实例化一组元素项,并且很容易与一个用于填充用户
    界面的定位器相结合。
//实现举例,repeater元素用于实现子元素的标号
import QtQuick 2.0
Column{
    spacing: 2
    Repeater{
        model: 10
        Rectangle{
            width: 100
            height: 20
            radius: 3
            color: "lightBlue"
            Text{
                anchors.centerIn: parent
                text: index
            }
        }
    }
}
//运行效果:

 
//借助JavaScript中的序列:
import QtQuick 2.0
Column{
    spacing: 2
    Repeater{
        model: ["Enterprise","Colombia","Challenger","Discovery","Endeavour","Atlantis"];
        Rectangle{
            width: 100
            height: 20
            radius: 3
            color: "lightBlue"
            Text{
                anchors.centerIn: parent
                text: index + ": " + modelData
            }
        }
    }
}
//运行效果:

 
//每个元素都提供了一个名字和一个元素
import QtQuick 2.0
Column{
    spacing: 2
    Repeater{
        model: ListModel{
            ListElement{ name: "Mercury"; surfaceColor: "gray" }
            ListElement{ name: "Venus"; surfaceColor: "yellow" }
            ListElement{ name: "Earth"; surfaceColor: "blue" }
            ListElement{ name: "Mars"; surfaceColor: "orange" }
            ListElement{ name: "Jupiter"; surfaceColor: "orange" }
            ListElement{ name: "Saturn"; surfaceColor: "yellow" }
            ListElement{ name: "Uranus"; surfaceColor: "lightBlue" }
            ListElement{ name: "Neptune"; surfaceColor: "lightBlue" }
        }
 
        Rectangle{
            width: 100
            height: 20
            radius: 3
            color: "lightBlue"
            Text{
                anchors.centerIn: parent
                text: name
            }
            Rectangle{  //圆
                anchors.left: parent.left
                anchors.verticalCenter: parent.verticalCenter
                anchors.leftMargin: 2
                width: 16
                height: 16
                radius: 8
                border.color: "black"
                border.width: 1
                color: surfaceColor
        }
    }
}
//运行效果:

 
import QtQuick 2.0
Column{
    spacing: 2
    Repeater{
        model: 10
        Rectangle{
            width: 100
            height: 20
            radius: 3
            color: "lightBlue"
            Text{
                anchors.centerIn: parent
                text: index
            }
        }
    }
}
//repeater的内容的每个子项实例化时绑定了默认的属性delegate,运行效果同第一段代码
/*****************************************************************************************************/
动态视图:
    //Repeater元素适合有限的静态数据,但在真正使用时,模型通常复杂庞大。QtQuick提供了ListView和GridView元素,
    //这两个都是基于可滑动区域的元素,用户可放入更大的数据。
//链表视图:
import QtQuick 2.0
Rectangle{
        width: 80
        height: 300
        color: "white"
 
        ListView{
            anchors.fill: parent
            anchors.margins: 20
            clip: true;     //显示超过parent尺寸时,不显示
            model: 100
            delegate: numberDelegate
            spacing: 5
        }
        Component{
            id: numberDelegate
            rectangle{
                width: 40
                height: 40
                color: "lightGreen"
                Text{
                    anchors.centerIn: parent
                    font.pixelSize: 10
                    text: index
                }
            }
        }
}
//视图末尾的行为是由boundsBehavior属性控制的,这是一个枚举值。Flickable.DragAndOvershootBounds默认模式下,
//内容到达最后会反弹回去;视图可通过边界线来拖拽和翻阅:Flickable.StopAtBounds,视图将不可移到边界线外;
//可以将视图拖拽到它的边界线外,但在边界线上翻阅将无效:Flickable.DragOverBounds
使用snapMode属性可以限制一个视图内元素的停止位置。默认是ListView.NoSnap,允许视图内元素在任何位置停止。
ListView.SnapToItem:视图顶部将会与元素对象的顶部对齐排列。ListView.SnapOneItem:当鼠标或触摸释放时,视图会停止在第一个可见元素
/********************************************************************************************************************************************/
方向:
//默认的链表视图只提供了一个垂直方向的滚动条,链表视图的方向由orientation控制,ListView.Vertical,ListView.Horizontal
//水平链表简例:
import QtQuick 2.0
Rectangle{
        width: 480
        height: 80
        color: "white"
 
        ListView{
            anchors.fill: parent
            anchors.margins: 20
            clip: true
            model: 100
            orientation: ListView.Horizontal
            delegate: numberDalegate
            spacing: 5
        }
        Component{
            id: numberDelegate
            Rectangle{
                width: 40
                height: 40
                color: "lightGreen"
                Text{
                    anchors.centerIn: parent
                    font.pixelSize: 10
                    text.index
                }
            }
        }
    }
//可以通过设置layoutDirection属性来控制元素顺序方向,可以被设置为Qt.LeftToRight  Qt.RightToLeft
/*****************************************************************************************************/
键盘导航和高亮:
当使用基于触摸方式的链表视图时,默认提供的视图已经足够使用。在使用键盘选择一个元素时,需要有标识当前选中元素
的机制。在QML中,这被叫做高亮。
import QtQuick 2.0
Rectangle{
        width: 240
        height: 300
        color: "white"
        ListView{
            anchors.fill: parent
            anchors.margins: 20
            clip: true
            model: 100
            delegate: numberDelegate
            spacing: 5
            highlight: highlightComponent   //指出使用的高亮代理元素
            focus: true
        }
        Component{
            id: hightlightComponent
            Rectangle{
                width: ListView.view.width
                color: "lightGreen"
            }
        }
        Component{
            id: numberDelegate
            Item{
                width: 40
                height: 40
                Text{
                    anchors.centerIn: parent
                    font.pixelSize: 10
                    text:index
                }
            }
        }
    }
//运行结果:

 
highlightRangeMode控制了高亮如何影响视图中当前的显示:
    默认设置ListView.NoHightlightRange意味着高亮与视图中元素的距离不相关
    ListView.StrictlyEnforceRange确保了高亮始终可见
    ListView.ApplyRange在需要的情况下高亮代理允许移出当前视图
默认配置下,视图负责高亮移动到指定位置,移动的速度和事件能够被改变:
    highlightMoveSpeed, highlightMoveDuration,
    highlightResizeSpeed, highlightResizeDuration
    默认速度:400像素,动作持续时间-1,若速度和持续时间都被设置,采用速度快的完成
为了更加详细的控制高亮的移动,highlightFollowCurrentItem属性设置为false,表示视图
不再负责高亮代理的移动,取而代之的是通过一个Behavior或者一个动画来控制它。
 
/* 下面例子中,高亮代理的y坐标属性与ListView.view.currentItem.y属性绑定,确保了高亮始终跟随当前元素。
  然而,我们没有让视图来移动这个高亮代理,所以我们需控制这个元素如何移动,通过Behavior on y完成 */
Component{
        id: highlightComponent
 
        Item{
            width: ListView.view.width
            height: ListView.view.currentItem.height
 
            y: ListView.view.currentItem.y
 
            Behavior on y{
                SequentialAnimation{
                    PropertyAnimation{
                        target: highlightRectangle
                        property: "opacity"
                        to: 0; duration: 200
                    }
                    NumberAnimation{ duration: 1 } //y发生变化,更该当前项的y值
                    PropertyAnimation{
                        target: highlightRectangle
                        property: "opacity"
                        to: 1; duration: 200
                    }
                }
            }
            Rectangle{
                id: highlightRectangle
                anchors.fill: parent
                color: "lightGreen"
            }
        }
    }
/*****************************************************************************************************/
页眉和页脚:
import QtQuick 2.0
Rectangle{
        width: 80
        height: 300
        color: "white"
 
        ListView{
            anchors.fill: parent
            anchors.margins: 20
            clip: true
            model: 4
            delegate: numberDelegate
            spacing: 5
            header: headerComponent     //页眉
            footer: footerComponent     //页脚
        }
        Component{
            id: headerComponent
            Rectangle{
                width: 40
                height: 20
                color: "yellow"
            }
        }
        Component{
            id: footerComponent
            Rectangle{
                width: 40
                height: 20
                color: "red"
            }
        }
        Component{
            id: numberDelegate
            Rectangle{
                width: 40
                height: 40
                color: "lightGreen"
                Text{
                    anchors.centerIn: parent
                    font.pixelSize: 10
                    text: index
                }
            }
        }
    }
//页眉页脚不遵循间隔属性,它们被直接放在链表元素之上或之下。页眉页脚的间隔必须通过页眉页脚元素自己设置
/************************************************************************************************************************/
网格视图:
    网格视图(GridView)不依赖与元素间隔和大小来配置元素。它使用单元宽度(cellWidth)和单元高度(cellHeight)
    来控制数组内二维元素的内容,每个元素从左上角开始一次放入单元格。
#import QtQuick 2.0
    Rectangle{
        width: 240
        height: 300
        color: "white"
        GridView{
            anchors.fill: parent
            anchors.margins: 20
            clip: true
            model: 100
            cellWidth: 45  //设置单元宽度
            cellHeight: 45   //设置单元高度
 
            delegate: numberDelegate
        }
        Component{
            id: numberDelegate
            Rectangle{
                width: 40
                height: 40
                color: "lightGreen"
                Text{
                    anchors.centerIn: parent
                    font.pixSize: 10
                    text: index
                }
            }
        }
    }
GridView也包含了页眉和页脚,也可以使用高亮代理并支持捕捉模式(snap)。它也可以使用不同的方向(orientation)
    与定向(direction)来定位。
定向使用flow属性来控制,可被设置为GridView.LeftToRight, GridView.TopToBottom
layoutDirection属性和flow属性能够适配网络从左到右或者从右到左
/***********************************************************************************************************/
代理(Delegate)
    当使用模型与视图来自定义用户界面时,代理在创建显示时扮演了大量的角色。模型中的每个元素通过代理来实现
    可视化,用户真实可见的是这些代理元素。
每个代理访问的索引号或者绑定的属性,一些是来自数据模型,一些来自视图。来自数据的数据将会通过属性传递到代理,
    来自视图的数据将会通过属性传递视图中与代理相关的状态信息。
通常使用的视图绑定属性是ListView.isCurrentItem和ListView.view.通过访问视图,可以创建可复用的代理,这些
    代理在被包含时会自动匹配视图的大小。
import QtQuick 2.0
Rectangle{
        width: 120
        height: 300
        color: "white"
 
        ListView{
            anchors.fill: parent
            anchors.margins: 20
            clip: true
            model: 100
            delegate: numberDelegate
            spacing: 5
            focus: true
        }
 
        Component{
            id: numberDelegate
            Rectangle{
                width: ListView.view.width   //代理的宽度和视图的宽度绑定
                height: 40
                color: ListView.isCurrentItem ? "gray" : "lightGray" //代理的背景颜色依赖于绑定的属性
 
                Text{
                    anchors.centerIn: parent
                    font.pixelSize: 10
                    text.index
                }
            }
        }
    }
如果在模型中的每个元素与一个动作相关,例如作用于一个元素时,这个功能是代理完成的。这是由事件管理分配给视图的,
这个操作控制了视图中元素的导航,代理控制了特定元素上的动作。
最基础的方法是在每个代理中创建一个MouseArea并且响应OnClicked信号。
/*******************************************************************************************************/
动画添加与移除元素:
import QtQuick 2.0
Rectangle{
        width: 480
        height: 300
        color: "white"
        ListModel{
            id: theModel
            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 }
            ListElement{ number: 9 }
        }
 
        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{   //点击时给模型添加一个元素
                anchors.fill: parent
                onClicked: {
                    theModel.append({"number": ++parent.count});
                }
            }
            property int count: 9
        }
 
        GridView{
            anchors.fill: parent
            anchors.margins: 20
            anchors.bottomMargin: 80
            clip: true
            model: theModel
            cellWidth: 45
            cellHeight: 45
 
            delegate: numberDelegate
        }
 
        Componment{     //点击代理时,移除一个元素
            id: numberDelegate
            Rectangle{
                id: wrapper
                width: 40
                height: 40
                color: "lightGreen"
                Text{
                    anchors.centerIn: parent
                    font.pixelSize: 10
                    text: number
                }
            }
 
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    if(!wrapper.GridView.delayRemove){
                        theModel.remove(index);
                    }
                }
            }
 
            GridView.onRemove: SequentialAnimation{
                PropertyAction{
                    target: wrapper;
                    property: "GridView.delayRemove"
                    value: true
                 }
            }
 
            GridView.onAdd: SequentialAnimation{
                NumberAnimation{
                    NumberAnimation{
                        target: wrapper
                        property: "scale"
                        from: 0; to: 1; duration:250
                        easing.type = ...
                    }
                }
            }
        }
 
    }
 
//形变的代理,路径视图,性能协调等知识就先不写了,写够了,路径视图等爱动弹时再单独补充吧
//本文主要翻译自英文文档。。。    
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值