赞
踩
When it comes to using models and views in a custom user interface, the delegate plays a huge role in creating a look and behaviour. As each item in a model is visualized through a delegate, what is actually visible to the user are the delegates.
在自定义用户界面中,使用模型和视图时,委托在创建外观和行为方面扮演着重要角色。由于模型中的每个项目都是通过委托可视化的,因此用户实际上看到的是委托。
Each delegate gets access to a number of attached properties, some from the data model, others from the view. From the model, the properties convey the data for each item to the delegate. From the view, the properties convey state information related to the delegate within the view. Let's dive into the properties from the view.
每个委托都可以访问许多附加的属性,有些来自数据模型,有些来自视图。从模型看,属性将每个项的数据传递给委托项。从视图看,属性传递与视图中的委托相关的状态信息。让我们从视图中深入了解属性。
The most commonly used properties attached from the view are ListView.isCurrentItem
and ListView.view
. The first is a boolean indicating if the item is the current item, while the latter is a read-only reference to the actual view. Through access to the view, it is possible to create general, reusable delegates that adapt to the size and nature of the view in which they are contained. In the example below, the width
of each delegate is bound to the width
of the view, while the background color
of each delegate depends on the attached ListView.isCurrentItem
property.
视图提供的最常用附加属性是ListView.isCurrentItem
和ListView.view
。前者是一个布尔值,指示该项是否为当前项,而后者是对实际视图的只读引用。通过对视图的访问,可以创建通用的、可重用的委托,以适应包含委托的视图的大小和性质。在下面的示例中,每个委托项的宽度width
都绑定到视图的宽度width
,而每个委托项的背景色color
取决于附加属性ListView.isCurrentItem
。
- import QtQuick
-
- Rectangle {
- width: 120
- height: 300
-
- gradient: Gradient {
- GradientStop { position: 0.0; color: "#f6f6f6" }
- GradientStop { position: 1.0; color: "#d7d7d7" }
- }
-
- ListView {
- anchors.fill: parent
- anchors.margins: 20
-
- focus: true
-
- model: 100
- delegate: numberDelegate
-
- spacing: 5
- clip: true
- }
-
- Component {
- id: numberDelegate
-
- Rectangle {
- id: wrapper
-
- required property int index
-
- width: ListView.view.width
- height: 40
-
- color: ListView.isCurrentItem ? "#157efb" : "#53d769"
- border.color: Qt.lighter(color, 1.1)
-
- Text {
- anchors.centerIn: parent
-
- font.pixelSize: 10
-
- text: wrapper.index
- }
- }
- }
- }
If each item in the model is associated with an action, for instance, clicking an item acts upon it, that functionality is a part of each delegate. This divides the event management between the view, which handles the navigation between items in the view, and the delegate which handles actions on a specific item.
如果模型中的每个项都与某个行为关联,例如,单击某个项对其进行行为操作,则该功能是每个委托的一部分。这将事件管理分为视图(处理视图中项目之间的导航)和委托(处理特定项目上的行为操作)。
The most basic way to do this is to create a MouseArea
within each delegate and act on the onClicked
signal. This is demonstrated in the example in the next section of this chapter.
最基本的方法是在每个委托中创建一个MouseArea,并对onClicked
信号进行响应操作。这将在本章下一节的示例中演示。
In some cases, the contents shown in a view changes over time. Items are added and removed as the underlying data model is altered. In these cases, it is often a good idea to employ visual cues to give the user a sense of direction and to help the user understand what data is added or removed.
在某些情况下,视图中显示的内容会随时间而变化。在更改基础数据模型时添加和删除项。在这些情况下,使用视觉提示给用户操作感,并帮助用户理解添加或删除的数据,通常是一个不错的主意。
Conveniently enough, QML views attach two signals, onAdd
and onRemove
, to each item delegate. By triggering animations from these, it is easy to create the movement necessary to aid the user in identifying what is taking place.
很方便,QML视图将两个信号onAdd和onRemove附加到每个委托项。通过触发这些,可以轻松创建必要的动画,以帮助用户识别正在发生的事情。
The example below demonstrates this through the use of a dynamically populated ListModel
. At the bottom of the screen, a button for adding new items is shown. When it is clicked, a new item is added to the model using the append
method. This triggers the creation of a new delegate in the view, and the emission of the GridView.onAdd
signal. The SequentialAnimation
called addAnimation
is started from the signal causes the item to zoom into view by animating the scale
property of the delegate.
下面的示例通过使用动态填充的ListModel演示了这一点。屏幕底部显示一个用于添加新项目的按钮。单击时,将使用append方法向模型中添加一个新项。这将触发在视图中创建新委托,并发出GridView.onAdd
信号。id为addAnimation的串行动画(SequentialAnimation
)从信号开始,通过设置委托的缩放属性的动画,使项目缩放到视图中。
- GridView.onAdd: addAnimation.start()
-
- SequentialAnimation {
- id: addAnimation
- NumberAnimation {
- target: wrapper
- property: "scale"
- from: 0
- to: 1
- duration: 250
- easing.type: Easing.InOutQuad
- }
- }
When a delegate in the view is clicked, the item is removed from the model through a call to the remove
method. This causes the GridView.onRemove
signal to be emitted, starting the removeAnimation
SequentialAnimation
. This time, however, the destruction of the delegate must be delayed until the animation has completed. To do this, PropertyAction
element is used to set the GridView.delayRemove
property to true
before the animation, and false
after. This ensures that the animation is allowed to complete before the delegate item is removed.
单击视图中的委托时,通过调用remove方法将该项从模型中移除。这将导致GridView.onRemove
发出信号,启动removeAnimation串行动画(SequentialAnimation)。但是,这一次,代理的销毁必须延迟到动画完成。为此,PropertyAction元素在动画完成前,将GridView.delayRemove
属性设置为true,在动画结束后设置为false。这样可以确保在删除委托项前,保证动画完成。
- GridView.onRemove: removeAnimation.start()
-
- SequentialAnimation {
- id: removeAnimation
-
- PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true }
- NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
- PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
- }
Here is the complete code:
以下是完整的代码:
- import QtQuick
-
- Rectangle {
- width: 480
- height: 300
-
- gradient: Gradient {
- GradientStop { position: 0.0; color: "#dbddde" }
- GradientStop { position: 1.0; color: "#5fc9f8" }
- }
-
- 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 {
- property int count: 9
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.margins: 20
-
- height: 40
-
- color: "#53d769"
- border.color: Qt.lighter(color, 1.1)
-
- Text {
- anchors.centerIn: parent
-
- text: "Add item!"
- }
-
- MouseArea {
- anchors.fill: parent
-
- onClicked: {
- theModel.append({"number": ++parent.count})
- }
- }
- }
-
- GridView {
- anchors.fill: parent
- anchors.margins: 20
- anchors.bottomMargin: 80
-
- clip: true
-
- model: theModel
-
- cellWidth: 45
- cellHeight: 45
-
- delegate: numberDelegate
- }
-
- Component {
- id: numberDelegate
-
- Rectangle {
- id: wrapper
-
- required property int index
- required property int number
-
- width: 40
- height: 40
-
- gradient: Gradient {
- GradientStop { position: 0.0; color: "#f8306a" }
- GradientStop { position: 1.0; color: "#fb5b40" }
- }
-
- Text {
- anchors.centerIn: parent
-
- font.pixelSize: 10
-
- text: wrapper.number
- }
-
- MouseArea {
- anchors.fill: parent
-
- onClicked: {
- if (wrapper.index == -1) {
- return
- }
- theModel.remove(wrapper.index)
- }
- }
-
- GridView.onRemove: removeAnimation.start()
-
- SequentialAnimation {
- id: removeAnimation
-
- PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true }
- NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
- PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
- }
-
- GridView.onAdd: addAnimation.start()
-
- SequentialAnimation {
- id: addAnimation
- NumberAnimation {
- target: wrapper
- property: "scale"
- from: 0
- to: 1
- duration: 250
- easing.type: Easing.InOutQuad
- }
- }
- }
- }
- }
A commonly used mechanism in lists is that the current item is expanded when activated. This can be used to dynamically let the item expand to fill the screen to enter a new part of the user interface, or it can be used to provide slightly more information for the current item in a given list.
列表中常用的一种机制是,当前项在激活时展开。这可以用于动态地让项目展开以填充屏幕,以进入用户界面的新部分,也可以用于为给定列表中的当前项目提供较多的信息显示。
In the example below, each item is expanded to the full extent of the ListView
containing it when clicked. The extra space is then used to add more information. The mechanism used to control this is a state expanded
that each item delegate can enter, where the item is expanded. In that state, a number of properties are altered.
在下面的示例中,单击时,每个项目都会扩展到包含它的ListView的全部范围。然后,额外的空间用于添加更多信息。用于控制种机制是每个委托项都可以进入的expanded
状态,expanded状态时,
其中项被展开。在这种状态下,许多属性都会发生变化。
First of all, the height
of the wrapper
is set to the height of the ListView
. The thumbnail image is then enlarged and moved down to make it move from its small position into its larger position. In addition to this, the two hidden items, the factsView
and closeButton
are shown by altering the opacity
of the elements. Finally, the ListView
is setup.
首先,wrapper
的高度height
设置为ListView的高度。然后放大并向下移动缩略图图像,使其从小位置移动到大位置。除此之外,两个隐藏项factsView和closeButton通过改变元素的不透明度opacity
来显示。最后,设置ListView。
Setting up the ListView
involves setting the contentsY
, that is the top of the visible part of the view, to the y
value of the delegate. The other change is to set interactive
of the view to false
. This prevents the view from moving. The user can no longer scroll through the list or change the current item.
设置ListView涉及将contentsY(视图可见部分的顶部)设置为委托项的y值。另一个更改是将视图的交互interactive
设置为false。这会阻止视图移动。用户无法再滚动列表或更改当前项目。
As the item first is clicked, it enters the expanded
state, causing the item delegate to fill the ListView
and the contents to rearrange. When the close button is clicked, the state is cleared, causing the delegate to return to its previous state and re-enabling the ListView
.
第一次单击项目时,它进入expanded
状态,导致项目委托填充ListView并重新排列内容。单击“关闭”按钮时,状态将被清除,从而使委托项返回到其以前的状态并重新启用ListView。
- import QtQuick
-
- Item {
- width: 300
- height: 480
-
- Rectangle {
- anchors.fill: parent
- gradient: Gradient {
- GradientStop { position: 0.0; color: "#4a4a4a" }
- GradientStop { position: 1.0; color: "#2b2b2b" }
- }
- }
-
- ListView {
- id: listView
-
- anchors.fill: parent
-
- delegate: detailsDelegate
- model: planets
- }
-
- ListModel {
- id: planets
-
- ListElement { name: "Mercury"; imageSource: "images/mercury.jpeg"; 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: "images/venus.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: "images/earth.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: "images/mars.jpeg"; 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
-
- required property string name
- required property string imageSource
- required property string facts
-
- width: listView.width
- height: 30
-
- Rectangle {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
-
- height: 30
-
- color: "#333"
- border.color: Qt.lighter(color, 1.2)
- Text {
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: 4
-
- font.pixelSize: parent.height-4
- color: '#fff'
-
- text: wrapper.name
- }
- }
-
-
- Rectangle {
- id: image
-
- width: 26
- height: 26
-
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.rightMargin: 2
- anchors.topMargin: 2
-
- color: "black"
-
-
- Image {
- anchors.fill: parent
-
- fillMode: Image.PreserveAspectFit
-
- source: wrapper.imageSource
- }
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked: parent.state = "expanded"
- }
-
- Item {
- id: factsView
-
- 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" }
- }
- border.color: '#000000'
- border.width: 2
-
- Text {
- anchors.fill: parent
- anchors.margins: 5
-
- clip: true
- wrapMode: Text.WordWrap
- color: '#1f1f21'
-
- font.pixelSize: 12
-
- text: wrapper.facts
- }
- }
- }
-
- Rectangle {
- id: closeButton
-
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.rightMargin: 2
- anchors.topMargin: 2
-
- width: 26
- height: 26
-
- color: "#157efb"
- border.color: Qt.lighter(color, 1.1)
-
- opacity: 0
-
- MouseArea {
- anchors.fill: parent
- onClicked: wrapper.state = ""
- }
- }
-
- states: [
- State {
- name: "expanded"
-
- PropertyChanges { target: wrapper; height: listView.height }
- PropertyChanges { target: image; width: listView.width; height: listView.width; 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"
- }
- }
- ]
- }
- }
- }
The techniques demonstrated here to expand the delegate to fill the entire view can be employed to make an item delegate shift shape in a much smaller way. For instance, when browsing through a list of songs, the current item could be made slightly larger, accommodating more information about that particular item.
此处演示是扩展委托项,以填充整个视图的技术,可用于使项目委托,以较小的形状移动。例如,当浏览歌曲列表时,当前项目可能会稍微变大,以容纳有关该特定项目的更多信息。
示例源码下载
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。