QML::模型与视图
模型与视图
QML中的一些视图项目(如 ListView、GridView和Repeater等)需要使用数据模型来为其提供数据进行显示。
这些项目通常也需要一个委托(delegate)组件来为模型中的每一个条目创建一个实例。
模型可以是静态的,也可以进行动态的修改、插人、移除或者移动项目。
1.01 ListModel
ListModel是一个简单的具有层次的元素, 可以使用ListElement 属性来指定可用的角色:
1. ListView用来进行显示,其中的数据模型model用来提供数据,委托delegate用来设置数据的显示方式
2. 在ListModel中,可以使用ListElement添加条目,每一个条目中可以有多种类型的角色,并且分别指定了它们的值。
3. 而委托可以使用一个组件来实现,在委托中可以直接绑定数据模型中的角色
4. 委托中还可以使用一个特殊的index角色,它包含了模型中条目的索引值。
5. 如果条目已经从模型中移除,那么其索引值为一1。所以如果在委托中绑定了index角色,那么一定要注意它的值有可能变为一1的情况。
Item {
width: 200; height: 250
ListModel {
id: myModel
ListElement { type: "Dog"; age: 8 }
ListElement { type: "Cat"; age: 5 }
}
Component {
id: myDelegate
Text { text: type + ", " + age }
}
ListView {
anchors.fill: parent
model: myModel
delegate: myDelegate
}
}
1.02 XmlListModel
1. XmlListModel允许从一个XML数据源创建一个模型,可以通过XmlRole 元素来指定一个角色。
2. 该数据模型一般用来显示从网络上获取的数据,因为网络上很多数据都可以使用XML格式进行读取,
这样就可以使用XmlListModel对其进行解析,然后显示出自己想要的数据。
所以使用该模型可以非常容易创建基于网络的应用程序,这也得益于QML中透明的网络传输以及内部的多线程支持。
1、query的值为“/rss/channel/item”,其指定了这个XmlListModel 应该从该XML文档的每一个<item>创建一个模型条目。
2. XmlRole对象定义了模型条目的属性。这里每一个条目都包含了title和pubDate属性,它们与相应的<item>中的title和pubDate值对应。
3. 还要指定值的类型,比如title是字符串,则使用string(),如果是数值,那么使用number()。
4. 注意XmlListModel数据是异步进行加载的,当加载完成时它的status属性会更改为XmlListModel.Ready。
这也就意味着当在视图中使用XmlListModel时,只有等到模型被加载完成后视图才会被填充。
5. 还可以将特定的角色定义为keys,这样当调用reload()重新加载数据时,模型只会在这些角色包含新的值时才进行添加或者刷新。
如:XmlRole( name:"pubDate";query:"pubDate/string()"; isKey: true )
Rectangle {
width: 360
height: 360
color: 'red'
XmlListModel {
id: feedModel
source: "../image/123.xml"
query: "/rss/channel/item"
XmlRole { name: "title"; query: "title/string()" }
XmlRole { name: "link"; query: "link/string()" }
XmlRole { name: "pubDate"; query: "pubDate/string()" }
}
ListView {
anchors.fill: parent
model: feedModel
delegate: Column {
Text { text: "title: " + title }
Text { text: "link: $" + link }
Text { text: "pubDate: $" + pubDate }
}
}
}
1.03 VisualltemModel
1. VisualltemModel允许使用QML项目作为模型。
2. 这个模型同时包含了数据和委托,在VisualltemModel中的子项目提供了委托的内容,该模型没有提供任何角色。
VisualDataModel{
id: itemModel
Rectangle {height: 30; width: 80; color: 'red'}
Rectangle {height: 30; width: 80; color: 'green'}
Rectangle {height: 30; width: 80; color: 'blue'}
}
ListView {
anchors.fill: parent
model: itemModel
}
1.04 VisualltemModel
可以在委托中访问使用该委托的视图及其属性:
1. 使用ListView时,可以在委托中使用ListView.view来进行访问。而且,还可以在委托中访问模型及其属性,可以使用ListView.view.model来访问。
2. 这对于在多个视图中使用相同的委托但对于每一个视图又想有不同特色的情况是非常有用的。
如在下面的例子中,委托显示了模型的language属性,而且使用了视图的 fruit_col-or属性来设置颜色。
3. 在委托中的一些动作(例如点击鼠标)需要更新模型中的数据,这时可以在模型中定义一个函数,
setData(int row, const OString & field name, OVariant new value)
然后在委托中合适的位置调用该函数.
ListView.view.model.setData(index,field, value)
Rectangle {
width: 200; height: 200
ListModel {
id: fruitModel
property string language: "en"
ListElement {
name: "Apple"
cost: 2.45
}
ListElement {
name: "Orange"
cost: 3.25
}
ListElement {
name: "Banana"
cost: 1.95
}
}
Component {
id: fruitDelegate
Row {
Text { text: " Fruit: " + name; color: ListView.view.fruit_color }
Text { text: " Cost: $" + cost }
Text { text: " Language: " + ListView.view.model.language }
}
}
ListView {
property color fruit_color: "green"
model: fruitModel
delegate: fruitDelegate
anchors.fill: parent
}
}
2.01 在QML 中呈现数据
1. QtQuick包含了一组可以使用不同方式呈现数据的标准项目。对于简单的用户界面,可以将Repeaters和Positioners一起使用来包含一些数据并将它们排列在用户界面上。
2. 当涉及大量的数据时,更好的办法是使用模型和视图来进行显示。视图是一个包含条目集合的可滚动容器,功能丰富,支持典型应用程序中的多种使用情况,而且还可以进行自定义风格和行为来满足需求。
3. 在QtQuick基本图形元素中提供了一组标准的视图:
ListView在水平或者垂直列表中排列条目;
GridView在可用空间中将条目排列在一个网格中;
PathView在路径上排列条目。
WebView不是一个功能完整的视图项目,
需要和Flickable项目一起使用来创建一个视图,实现的功能与网页浏览器相似。
2.02 ListView
1. ListView可以显示一个水平或者垂直放置条目的条目列表。
2. ListView拥有一个模型model属性,用来定义要显示的数据,还有一个委托delegate属性,用来定义数据显示的方式。
3. ListView默认具有弹动效果,因为它继承自Flickable项目。
4. 模型也可以定义在一个独立的文件中,然后像一般的组件一样来使用它。
5. ListView.isCurrentltem可以用来判断一个条目是否是当前条目。
6. contactInfo对象必须使用 wrapper.ListView.isCurrentltem来访问该属性。
//ContactModel.qml
ListModel {
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
}
import QtQuick 2.12
import QtQuick.Window 2.12
ListView {
width: 180; height: 200
Component {
id: contactsDelegate
Rectangle {
id: wrapper
width: 180
height: contactInfo.height
color: ListView.isCurrentItem ? "black" : "red"
Text {
id: contactInfo
text: name + ": " + number
color: wrapper.ListView.isCurrentItem ? "red" : "black"
}
}
}
model: ContactModel {}
delegate: contactsDelegate
focus: true
}
2.03 GridView
GridView与ListView的概念以及使用方法是非常相似的,主要的不同之处就是GridView是将条目排列成网格。
Rectangle {
width: 300; height: 400
color: "white"
ListModel {
id: appModel
ListElement { name: "Music"; icon: "AudioPlayer_48.png" }
ListElement { name: "Movies"; icon: "VideoPlayer_48.png" }
ListElement { name: "Camera"; icon: "Camera_48.png" }
ListElement { name: "Calendar"; icon: "DateBook_48.png" }
ListElement { name: "Messaging"; icon: "EMail_48.png" }
ListElement { name: "Todo List"; icon: "TodoList_48.png" }
ListElement { name: "Contacts"; icon: "AddressBook_48.png" }
}
Component {
id: appDelegate
Item {
width: 100; height: 100
Image {
id: myIcon
y: 20; anchors.horizontalCenter: parent.horizontalCenter
source: icon
}
Text {
anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
text: name
}
}
}
Component {
id: appHighlight
Rectangle { width: 80; height: 80; color: "lightsteelblue" }
}
GridView {
anchors.fill: parent
cellWidth: 100; cellHeight: 100
highlight: appHighlight
focus: true
model: appModel
delegate: appDelegate
}
}
2.04 PathView
PathView与ListView、GridView最大的不同之处在于它是在一个路径(Path)上排列条目的。
Rectangle {
width: 400; height: 240
color: "white"
ListModel {
id: appModel
ListElement { name: "Music"; icon: "AudioPlayer_48.png" }
ListElement { name: "Movies"; icon: "VideoPlayer_48.png" }
ListElement { name: "Camera"; icon: "Camera_48.png" }
ListElement { name: "Calendar"; icon: "DateBook_48.png" }
ListElement { name: "Messaging"; icon: "EMail_48.png" }
ListElement { name: "Todo List"; icon: "TodoList_48.png" }
ListElement { name: "Contacts"; icon: "AddressBook_48.png" }
}
Component {
id: appDelegate
Item {
width: 100; height: 100
scale: PathView.iconScale
Image {
id: myIcon
y: 20; anchors.horizontalCenter: parent.horizontalCenter
source: icon
smooth: true
}
Text {
anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
text: name
smooth: true
}
MouseArea {
anchors.fill: parent
onClicked: view.currentIndex = index
}
}
}
Component {
id: appHighlight
Rectangle { width: 80; height: 80; color: "lightsteelblue" }
}
PathView {
id: view
anchors.fill: parent
highlight: appHighlight
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
focus: true
model: appModel
delegate: appDelegate
path: Path {
startX: 10
startY: 50
PathAttribute { name: "iconScale"; value: 0.5 }
PathQuad { x: 200; y: 150; controlX: 50; controlY: 200 }
PathAttribute { name: "iconScale"; value: 1.0 }
PathQuad { x: 390; y: 50; controlX: 350; controlY: 200 }
PathAttribute { name: "iconScale"; value: 0.5 }
}
}
}
2.05 WebView
WebView主要用来对网页内容进行渲染,只需为其指定一个URL即可。在使用该元素时需要先导人QtWebKit模块。
Flickable {
width: 400; height: 300
contentWidth: webView.width; contentHeight: webView.height
WebView {
id: webView
url: "http://www.baidu.com"
}
}