QML中動態(tài)與靜態(tài)模型應(yīng)用詳解
前言
對于開發(fā)用戶界面,最重要的就是保持?jǐn)?shù)據(jù)與UI分離。數(shù)據(jù)通常被稱為為model,可視化處理稱作view。在QML中,model與view都通過delegate連接起來。功能劃分如下,model提供數(shù)據(jù),對于每個數(shù)據(jù)項,可能有很多個值。顯示在view(視圖)中的每項數(shù)據(jù),都是通過delegate(代理)來實現(xiàn)可視化的。view(視圖)的任務(wù)是排列這些delegate(代理),每個delegate(代理)將model item(模型項)的值呈現(xiàn)給用戶。

一個模型可以是一個整數(shù),提供給代理使用的索引值(index).如果JavaScript數(shù)組被作為一個模型,模型數(shù)據(jù)變量(modelData)代表了數(shù)組的數(shù)據(jù)的當(dāng)前索引。對于更加復(fù)雜的情況,每個數(shù)據(jù)項需要提供多個值,可以使用ListModel與ListElement。
對于靜態(tài)模型,一個Repeater可以被用作視圖。它可以非常方便的使用行(Row),列(Column),柵格(Grid),或者流(Flow)來創(chuàng)建用戶界面。對于動態(tài)或者更大的數(shù)據(jù)模型,使用ListView或者GridView更加合適。它們會在需要時動態(tài)的創(chuàng)建代理,減少在場景下一次顯示的元素的數(shù)量。
在視圖中的代理可以與數(shù)據(jù)模型中的屬性靜態(tài)綁定或者動態(tài)綁定。使用onAdd與onRemove信號,可以動態(tài)的播放他們的添加和移除的特效。
靜態(tài)模型
通過Repeater來作視圖,用來創(chuàng)建一些靜態(tài)的顯示界面。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("靜態(tài)模型")
//靜態(tài)顯示單一的數(shù)據(jù)模型
Column{
id: column1
spacing: 10
Repeater{
model: 4
Rectangle{
width:300
height: 40
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: index
}
}
}
}
//靜態(tài)顯示列表數(shù)據(jù)模型
Column{
id: column2
anchors.top: column1.bottom
anchors.topMargin: 10
spacing: 10
Repeater{
model: ["Enterpris","Colombia","Challenger","Discover"]
Rectangle{
width:300
height: 40
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: index + ":" + modelData
}
}
}
}
//使用多元素的ListModel
Row{
id: listModelItem
anchors.top: column2.bottom
anchors.topMargin: 10
spacing: 10
Repeater{
model: ListModel{
ListElement{name : "項目1";surfaceColor: "gray";}
ListElement{name : "項目2";surfaceColor: "orange";}
ListElement{name : "項目3";surfaceColor: "red";}
}
Rectangle{
width: 150
height: 40
radius: 3
color: "lightBlue"
Text {
anchors.left: circleItem.right
anchors.leftMargin: 10
anchors.centerIn: parent
text: name
}
Rectangle{
id: circleItem
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 4
width: 32
height: 32
radius: 16
border.color: "black"
border.width: 2
color: surfaceColor
}
}
}
}
Row{
spacing: 5
anchors.top: listModelItem.bottom
anchors.topMargin: 10
Repeater{
model:4
delegate: Rectangle{
width: 150
height: 40
radius: 3
color: "lightBlue"
Text {
anchors.centerIn: parent
text: index
}
}
}
}
}顯示效果如下圖所示:

動態(tài)模型
Repeator元素適合有限的靜態(tài)元素,但是真正使用的時候,模型通常更加復(fù)雜和龐大。QtQuick提供了ListView和GridView元素,這兩個都是基于Flickable區(qū)域的元素,因此用戶可以放入更大的數(shù)據(jù)。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("動態(tài)模型")
Rectangle{
id: rowView
width: 80
height: 300
color: "white"
ListView{
anchors.fill: parent
anchors.margins: 20
//是否對邊界進行裁剪
clip: true
model: 5
delegate: numberDelegate
//列表顯示是水平還是垂直
orientation: ListView.Vertical
//focus: true
spacing: 10
//頁眉和頁腳
header: headerComponent
footer: footerComponent
}
Component{
id: numberDelegate
//必須使用Item做為基本元素
Rectangle{
width: 40
height: 40
color:"lightGreen"
Text {
anchors.centerIn: parent
font.pixelSize: 15
text: index
}
}
}
Component{
id: headerComponent
Rectangle{
width: 40
height: 20
color: "yellow"
}
}
Component{
id: footerComponent
Rectangle{
width: 40
height: 20
color: "yellow"
}
}
}
Rectangle{
id: gridView
width: 240
height: 300
color: "white"
anchors.left: rowView.right
GridView{
anchors.fill: parent
anchors.margins: 20
//是否對邊界進行裁剪
clip: true
model: 100
delegate: gridDelegate
cellHeight: 45
cellWidth: 45
focus: true
}
Component{
id: gridDelegate
//必須使用Item做為基本元素
Rectangle{
width: 40
height: 40
color: GridView.isCurrentItem? "Green":"lightGreen"
Text {
anchors.centerIn: parent
font.pixelSize: 10
text: index
}
}
}
}
}顯示效果如下圖所示:

有時候我們需要根據(jù)需要動態(tài)的向數(shù)據(jù)模型中添加或者刪除元素,這時候我們需要了解元素添加和移除的接口。為了方便使用,QML為每個視圖綁定了兩個信號,onAdd和onRemove.使用動畫連接它們,可以方便的創(chuàng)建識別哪些內(nèi)容被添加或刪除的動畫。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("動態(tài)添加和刪除元素")
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}
}
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
}
Component{
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 }
NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
}
//模型元素添加的時候的動畫
GridView.onAdd: SequentialAnimation {
NumberAnimation { target: wrapper; property: "scale"; from: 0; to: 1; duration: 250; easing.type: Easing.InOutQuad }
}
}
}
}
}顯示效果如下圖所示:

在使用鏈表時通常會使用當(dāng)前項激活時展開的機制。這個操作可以被用于動態(tài)的將當(dāng)前項目填充到整個屏幕來添加一個新的用戶界面,或者為鏈表中的當(dāng)前項提供更多的信息。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("動畫與數(shù)據(jù)模型組合使用")
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
}
//數(shù)據(jù)模型
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
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: 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: 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: facts
}
}
}
Rectangle {
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 = ""
}
}
//通過狀態(tài)切換來更改界面控件的狀態(tài)
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"
}
}
]
}
}
}
}顯示效果如下圖所示:

到此這篇關(guān)于QML中動態(tài)與靜態(tài)模型應(yīng)用詳解的文章就介紹到這了,更多相關(guān)QML模型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 內(nèi)存分配處理函數(shù)set_new_handler的使用
這篇文章主要介紹了C++ 內(nèi)存分配處理函數(shù)set_new_handler的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
MFC中動態(tài)創(chuàng)建控件以及事件響應(yīng)實現(xiàn)方法
這篇文章主要介紹了MFC中動態(tài)創(chuàng)建控件以及事件響應(yīng)實現(xiàn)方法,詳細(xì)講解了MFC中動態(tài)創(chuàng)建控件以及事件響應(yīng)的概念與實現(xiàn)方法,具有一定的實用價值,需要的朋友可以參考下2014-10-10
VS Code 中搭建 Qt 開發(fā)環(huán)境方案分享
這篇文章主要介紹了VS Code 中搭建 Qt 開發(fā)環(huán)境方案分享的相關(guān)資料,需要的朋友可以參考下2022-12-12
Linux下semop等待信號時出現(xiàn)Interrupted System Call錯誤(EINTR)解決方法
本篇文章是對在Linux下semop等待信號時出現(xiàn)Interrupted System Call錯誤(EINTR)的解決方法進行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C++中構(gòu)造函數(shù)與析構(gòu)函數(shù)的詳解及其作用介紹
這篇文章主要介紹了C++中構(gòu)造函數(shù)與析構(gòu)函數(shù)的詳解及其作用介紹,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09

