若该文为原创文章,转载请注明原文出处
作为一种经典的架构模式,通过把职责、性质相近的成分归结在一起,不相近的进行隔离,MVC将系统分解为模型、视图、控制器三部分,每一部分都相对独立,职责单一。MVC是对系统复杂性的一种合理的梳理与切分,它的思想实质就是“关注点分离”。
QT中的Model-View编程框架,对Controller部分做了改动,引入了Delegate的概念,合起来就是Model-View-Delegate。
在QT C++中,对Model-View-Delegate已经做了基础的实现,不必去设计Model-View框架,只需学习Qt给的框架即可。
ListView用来一个条目列表,条目对应的数据来自于Model, 而每个条目的外观则由Delegate决定。
要使用ListView,必须指定一个Model、一个Delegate。
Model可以是QML内建类型,如ListModel、XmlListModel,也可以是在C++实现的QAbstractItemModel或QAbstractListModel的派生类。
修改main.qml内容:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import MyObj 1.0
Window {
id: window
visible: true
width: 600
height: 480
title: qsTr("Hello World")
Rectangle {
width: 360
height: 300
color: "#EEEEEE"
Component {
id: phoneDelegate
Item {
id: wrapper
width: parent.width
height: 30
MouseArea {
anchors.fill: parent
onClicked: wrapper.ListView.view.currentIndex = index
}
RowLayout {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Text {
id: coll
text: name
color: wrapper.ListView.isCurrentItem ? "red" : "black"
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.preferredWidth: 120
}
Text {
text: cost
color: wrapper.ListView.isCurrentItem ? "red" : "black";
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.preferredWidth: 80
}
Text {
text: manufacturer
color: wrapper.ListView.isCurrentItem ? "red" : "black";
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.fillWidth: true
}
}
}
}
ListView {
id: listView
anchors.fill: parent
delegate: phoneDelegate
model: ListModel {
id: phoneModel
ListElement {
name: "iPhone 3gs"
cost: "1000"
manufacturer: "Apple"
}
ListElement {
name: "iphone 4"
cost: "1800"
manufacturer: "Apple"
}
ListElement {
name: "iphone 5"
cost: "2800"
manufacturer: "Apple"
}
ListElement {
name: "iphone 6"
cost: "3800"
manufacturer: "Apple"
}
ListElement {
name: "iphone 8"
cost: "4800"
manufacturer: "Apple"
}
}
focus: true
highlight: Rectangle {
color: "lightblue"
}
}
}
}
编译运行:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import MyObj 1.0
Window {
id: window
visible: true
width: 600
height: 480
title: qsTr("Hello World")
Rectangle {
width: 360
height: 300
color: "#EEEEEE"
Component {
id: phoneModel
ListModel {
ListElement {
name: "iPhone 3"
cost: "1000"
manufacturer: "Apple"
}
ListElement {
name: "iPhone 4"
cost: "2000"
manufacturer: "Apple"
}
ListElement {
name: "iPhone 5"
cost: "3000"
manufacturer: "Apple"
}
ListElement {
name: "iPhone 6"
cost: "4000"
manufacturer: "Apple"
}
}
}
Component {
id: headerView
Item {
width: parent.width
RowLayout {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Text {
text: "Name"
font.bold: true
font.pixelSize: 20
Layout.preferredWidth: 120
}
Text {
text: "Cost"
font.bold: true
font.pixelSize: 20
Layout.preferredWidth: 80
}
Text {
text: "Manufacturer"
font.bold: true
font.pixelSize: 20
Layout.fillWidth: true
}
}
}
}
Component {
id: footerView
Text {
width: parent.width
font.italic: true
color: "blue"
height: 30
verticalAlignment: Text.AlignVCenter
}
}
Component {
id: phoneDelegate
Item {
id: wrapper
width: parent.width
height: 30
MouseArea {
anchors.fill: parent
onClicked: wrapper.ListView.view.currentIndex = index
}
RowLayout {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Text {
id: coll
text: name
color: wrapper.ListView.isCurrentItem ? "red" : "black"
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.preferredWidth: 120
}
Text {
text: cost
color: wrapper.ListView.isCurrentItem ? "red" : "black";
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.preferredWidth: 80
}
Text {
text: manufacturer
color: wrapper.ListView.isCurrentItem ? "red" : "black";
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.fillWidth: true
}
}
}
}
ListView {
id: listView
anchors.fill: parent
delegate: phoneDelegate
model: phoneModel.createObject(listView)
header: headerView
footer: footerView
focus: true
highlight: Rectangle {
color: "lightblue"
}
onCurrentIndexChanged: {
if(listView.currentIndex >= 0) {
var data = listView.model.get(listView.currentIndex);
listView.footerItem.text = data.name + "," + data.cost + "," + data.manufacturer;
} else {
listView.footerItem.text = "-";
}
}
}
}
}
编译结果:
ListModel的count属性表示Model中有多少条数据。
ListModel的get()方法接受一个int类型的参数,用来获取指定索引位置的数据返回一个QML对象。
然后,我们就可以像访问属性那样访问数据的role。
eq:
var data = listView.model.get(listView.currentIndex);
console.log(data.name + "," + data.cost + "," + data.manufacturer);
ListModel的remove(int index, int count)方法,删除一条或多条数据。
eq:
MouseArea {
anchors.fill: parent
onClicked: {
wrapper.ListView.view.currentIndex = index;
}
onDoubleClicked: {
wrapper.ListView.view.model.remove(index);
}
}
修改数据使用的是ListModel的setProperty(int index, string property, variant value)方法。
比如:修改价格
listView.model.setProperty(5, "cost", 16999)
添加数据使用的是append()方法。
eq:
listView.model.append (
{
"name" : "mx3"
"cost" : "1978"
"manufacturer" : "Meizu"
}
)
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import MyObj 1.0
Window {
id: window
visible: true
width: 600
height: 480
title: qsTr("Hello World")
Rectangle {
width: 360
height: 300
color: "#EEEEEE"
Component {
id: phoneModel
ListModel {
ListElement {
name: "iPhone 3"
cost: "1000"
manufacturer: "Apple"
}
ListElement {
name: "iPhone 4"
cost: "2000"
manufacturer: "Apple"
}
ListElement {
name: "iPhone 5"
cost: "3000"
manufacturer: "Apple"
}
ListElement {
name: "iPhone 6"
cost: "4000"
manufacturer: "Apple"
}
}
}
Component {
id: headerView
Item {
width: parent.width
height: 30
RowLayout {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Text {
text: "Name"
font.bold: true
font.pixelSize: 20
Layout.preferredWidth: 120
}
Text {
text: "Cost"
font.bold: true
font.pixelSize: 20
Layout.preferredWidth: 80
}
Text {
text: "Manufacturer"
font.bold: true
font.pixelSize: 20
Layout.fillWidth: true
}
}
}
}
Component {
id: footerView
Item {
id: footerRootItem
width: parent.width
height: 30
property alias text: txt.text
signal clean()
signal add()
Text {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
id: txt
font.italic: true
color: "blue"
verticalAlignment: Text.AlignVCenter
}
Button {
id: clearAll
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: "Clear"
onClicked: footerRootItem.clean();
}
Button {
id: addOne
anchors.right: clearAll.left
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
text: "Add"
onClicked: footerRootItem.add()
}
}
}
Component {
id: phoneDelegate
Item {
id: wrapper
width: parent.width
height: 30
MouseArea {
anchors.fill: parent
onClicked: wrapper.ListView.view.currentIndex = index
}
RowLayout {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Text {
id: coll
text: name
color: wrapper.ListView.isCurrentItem ? "red" : "black"
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.preferredWidth: 120
}
Text {
text: cost
color: wrapper.ListView.isCurrentItem ? "red" : "black";
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.preferredWidth: 80
}
Text {
text: manufacturer
color: wrapper.ListView.isCurrentItem ? "red" : "black";
font.pixelSize: wrapper.ListView.isCurrentItem ? 22 : 18
Layout.fillWidth: true
}
}
}
}
ListView {
id: listView
anchors.fill: parent
delegate: phoneDelegate
model: phoneModel.createObject(listView)
header: headerView
footer: footerView
focus: true
highlight: Rectangle {
color: "lightblue"
}
onCurrentIndexChanged: {
if(listView.currentIndex >= 0) {
var data = listView.model.get(listView.currentIndex);
listView.footerItem.text = data.name + "," + data.cost + "," + data.manufacturer;
} else {
listView.footerItem.text = "-";
}
}
function addOne() {
model.append(
{
"name" : "MX3",
"cost": "1233",
"manufacturer": "Meizu"
});
}
Component.onCompleted: {
listView.footerItem.clean.connect(listView.model.clear);
listView.footerItem.add.connect(listView.addOne);
}
}
}
}
编译结果:
如有侵权,请及时联系博主删除,VX:18750903063