qml基础学习 模型视图

Posted 朝十晚八

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了qml基础学习 模型视图相关的知识,希望对你有一定的参考价值。

一、理解qml模型和视图

    qt的发展是迅速的,虽然在每一个release版本中或多或少都有bug,但是作为一个庞大的gui库,no,应该说是一个开发框架开说,qt已经算是做的相当好。qml部分是qt4.7的时候推出的,当时qml只是为了移动端而设计的开发语言,随着it行业的发展,桌面端也产生了一定的需求,这就使得qml也必须支持桌面端的开发。使用qml可以做出绚丽的界面,并把逻辑和界面展示分开,qml和C++就好比htmljavascript

    qt中有大量的model/view类,视图类:QTableView、QListView和QTreeView,模型类:QAbstractTableModel、QAbstractListModel和QAbstractProxyModel,这三个模型类都是继承自QAbstractItemModel。对于qml语言来说,也有model和view,他们分别就是GridView、ListView和PathView,其中GridView和ListView在qt中都有对于的实现类,PathView是最难理解的view,也是最灵活的view,他可以做出各种各样比较绚丽的效果。

二、效果展示

    这一节我们主要是说明qml中的视图类,如下效果图展示的那样,图1是用GridView实现,图2是用ListView实现,view的item项都是用代理进行绘制;图3是用PathView实现的一个效果图,类似于一个卡牌弹出弹入效果。

    顺道提一嘴,qml文件都是可以使用qmlscene.exe来预览

 图1 gridview效果图

图2 listview效果图

 图3 pathview效果图

三、源码分析

    每一个示例中都有大量的注释,具体细节可以参看注释

1、GridView增删

    如图1所示,这是一个GridView的简单示例,示例完成单击Add Item按钮实现新增项,点击项实现删除等功能。

  1 import QtQuick 2.0
  2 
  3 Rectangle {
  4     width: 480;
  5     height: 300;
  6 
  7     //背景色渐变
  8     gradient: Gradient {
  9         GradientStop { position: 0.0; color: "#dbddde"; }
 10         GradientStop { position: 1.0; color: "#5fc9f8"; }
 11     }
 12 
 13     //list模型默认9项
 14     ListModel {
 15         id: theModel
 16 
 17         ListElement { number: 0; }
 18         ListElement { number: 1; }
 19         ListElement { number: 2; }
 20         ListElement { number: 3; }
 21         ListElement { number: 4; }
 22         ListElement { number: 5; }
 23         ListElement { number: 6; }
 24         ListElement { number: 7; }
 25         ListElement { number: 8; }
 26         ListElement { number: 9; }
 27     }
 28 
 29     //Add Item按钮
 30     Rectangle {
 31         anchors.left: parent.left;
 32         anchors.right: parent.right;
 33         anchors.bottom: parent.bottom;
 34         anchors.margins: 20;
 35 
 36         height: 40;
 37 
 38         color: "#53d769";
 39         border.color: Qt.lighter(color, 1.1);
 40 
 41         Text {
 42             anchors.centerIn: parent;
 43 
 44             text: "Add item!";
 45         }
 46 
 47         //点击时新增项  实现model的动态新增
 48         MouseArea {
 49             anchors.fill: parent;
 50 
 51             onClicked: {
 52                 theModel.append({"number": ++parent.count});
 53             }
 54         }
 55 
 56         property int count: 9;//
 57     }
 58 
 59     GridView {
 60         anchors.fill: parent;
 61         anchors.margins: 20;
 62         anchors.bottomMargin: 80;
 63 
 64         clip: true;
 65 
 66         model: theModel;//绑定数据源
 67 
 68         cellWidth: 45;//设置项大小
 69         cellHeight: 45;
 70 
 71         delegate: numberDelegate;//设置绘制代理
 72     }
 73 
 74     //自定义绘制代理
 75     Component {
 76         id: numberDelegate;
 77 
 78         Rectangle {
 79             id: wrapper;
 80 
 81             width: 40;
 82             height: 40;
 83 
 84             //首先是一个渐变的矩形框
 85             gradient: Gradient {
 86                 GradientStop { position: 0.0; color: "#f8306a"; }
 87                 GradientStop { position: 1.0; color: "#fb5b40"; }
 88             }
 89 
 90             //文本值是number的数值
 91             Text {
 92                 anchors.centerIn: parent;
 93 
 94                 font.pixelSize: 10;
 95 
 96                 text: number;
 97             }
 98 
 99             //鼠标点击代理时,移除点击项
100             MouseArea {
101                 anchors.fill: parent;
102 
103                 onClicked: {
104                     if (!wrapper.GridView.delayRemove)//是否延迟移除
105                     {
106                         theModel.remove(index);
107                     }
108                 }
109             }
110 
111             //GridView移除项  顺序动画
112             GridView.onRemove: SequentialAnimation {
113                 //属性变化
114                 PropertyAction {
115                     target: wrapper;
116                     property: "GridView.delayRemove";
117                     value: true;
118                 }
119                 //数字动画
120                 NumberAnimation {
121                     target: wrapper;//目标对象
122                     property: "scale";//执行动画的属性
123                     to: 0;//结束值
124                     duration: 250;//动画持续时长
125                     easing.type: Easing.InOutQuad;//动画执行曲线
126                 }
127                 PropertyAction {
128                     target: wrapper;
129                     property: "GridView.delayRemove";
130                     value: false;
131                 }
132             }
133 
134             //GridView新增项  顺序动画
135             GridView.onAdd: SequentialAnimation {
136                 NumberAnimation {
137                     target: wrapper;
138                     property: "scale";
139                     from: 0;//开始值
140                     to: 1;
141                     duration: 250;
142                     easing.type: Easing.InOutQuad;
143                 }
144             }
145         }
146     }
147 }

2、列表

    如图2所示,是一个使用ListView实现的列表控件,点击列表控件中的项,可以实现最大化来展示列表的详细信息

  1 import QtQuick 2.0
  2 
  3 Item {
  4     width: 300;
  5     height: 480;
  6 
  7     //渐变别景色
  8     Rectangle {
  9         anchors.fill: parent;
 10         gradient: Gradient {
 11             GradientStop { position: 0.0; color: "#4a4a4a"; }
 12             GradientStop { position: 1.0; color: "#2b2b2b"; }
 13         }
 14     }
 15 
 16     //主界面列表视图
 17     ListView {
 18         id: listView;
 19 
 20         anchors.fill: parent;
 21 
 22         delegate: detailsDelegate;//设置绘制代理
 23         model: planets;//绑定数据源
 24     }
 25 
 26     ListModel {
 27         id: planets;
 28 
 29         ListElement {
 30             name: "Mercury";
 31             imageSource: "images/mercury.jpeg";
 32             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." ;
 33         }
 34         ListElement {
 35             name: "Venus";
 36             imageSource: "images/venus.jpeg";
 37             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.";
 38         }
 39         ListElement {
 40             name: "Earth";
 41             imageSource: "images/earth.jpeg";
 42             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\'.";
 43         }
 44         ListElement {
 45             name: "Mars";
 46             imageSource: "images/mars.jpeg";
 47             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.";
 48         }
 49     }
 50 
 51     Component {
 52         id: detailsDelegate;
 53 
 54         Item {
 55             id: wrapper;
 56 
 57             width: listView.width;
 58             height: 30;
 59 
 60             //列表项文本
 61             Rectangle {
 62                 anchors.left: parent.left;
 63                 anchors.right: parent.right;
 64                 anchors.top: parent.top;
 65 
 66                 height: 30;
 67 
 68                 color: "#333";
 69                 border.color: Qt.lighter(color, 1.2);
 70                 Text {
 71                     anchors.left: parent.left;
 72                     anchors.verticalCenter: parent.verticalCenter;
 73                     anchors.leftMargin: 4;
 74 
 75                     font.pixelSize: parent.height-4;
 76                     color: \'#fff\';
 77 
 78                     text: name;//ListElement中的name
 79                 }
 80             }
 81 
 82             //列表项图标
 83             Rectangle {
 84                 id: image;
 85 
 86                 width: 26;
 87                 height: 26;
 88 
 89                 anchors.right: parent.right;
 90                 anchors.top: parent.top;
 91                 anchors.rightMargin: 2;
 92                 anchors.topMargin: 2;
 93 
 94                 color: "yellow";
 95 
 96                 Image {
 97                     anchors.fill: parent;
 98 
 99                     fillMode: Image.PreserveAspectFit;
100 
101                     source: imageSource;//ListElement中的imageSource
102                 }
103             }
104 
105             //鼠标点击列表项 进行状态前切换,
106             MouseArea {
107                 anchors.fill: parent;
108                 onClicked: parent.state = "expanded";//切换到展开状态
109             }
110 
111             //详情页展开时,文本详细信息
112             Item {
113                 id: factsView;
114 
115                 anchors.top: image.bottom;//位于放大后的图标底部
116                 anchors.left: parent.left;
117                 anchors.right: parent.right;
118                 anchors.bottom: parent.bottom;
119 
120                 opacity: 0;//默认透明不显示  当点击代理项时该属性会慢慢变得可见
121 
122                 Rectangle {
123                     anchors.fill: parent;
124 
125                     gradient: Gradient {
126                         GradientStop { position: 0.0; color: "#fed958"; }
127                         GradientStop { position: 1.0; color: "#fecc2f"; }
128                     }
129                     border.color: \'#000000\';
130                     border.width: 2;
131 
132                     Text {
133                         anchors.fill: parent;
134                         anchors.margins: 5;
135 
136                         clip: true;//可剪切
137                         wrapMode: Text.WordWrap;//文本支持换行
138                         color: \'#1f1f21\';
139 
140                         font.pixelSize: 12;
141 
142                         text: facts;
143                     }
144                 }
145             }
146 
147             //项最大化时 右上角关闭按钮
148             Rectangle {
149                 id: closeButton;
150 
151                 anchors.right: parent.right;
152                 anchors.top: parent.top;
153                 anchors.rightMargin: 2;
154                 anchors.topMargin: 2;
155 
156                 width: 26;
157                 height: 26;
158 
159                 color: "#157efb";
160                 border.color: Qt.lighter(color, 1.1);
161 
162                 opacity: 0;
163 
164                 MouseArea {
165                     anchors.fill: parent;
166                     onClicked: wrapper.state = "";//点击恢复到默认状态
167                 }
168             }
169 
170             //自定义代理状态
171             states: [
172                 State {
173                     name: "expanded";
174                     //在点击列表项后 各项属相变化
175 
176                     //代理高度铺满视图高度
177                     PropertyChanges { target: wrapper; height: listView.height; }
178                     //列表项的图标放大
179                     PropertyChanges {
180                         target: image;
181                         width: listView.width;
182                         height: listView.width;
183                         anchors.rightMargin: 0;
184                         anchors.topMargin: 30//距离顶部30像素
185                     }
186                     //文本详细信息可见
187                     PropertyChanges { target: factsView; opacity: 1; }
188                     //关闭按钮可见
189                     PropertyChanges { target: closeButton; opacity: 1; }
190                     //列表项视图
191                     PropertyChanges {
192                         target: wrapper.ListView.view;
193                         contentY: wrapper.y;
194                         interactive: false
195                     }
196                 }
197             ]
198 
199             //项变化时 过程
200             transitions: [
201                 Transition {
202                     NumberAnimation {
203                         duration: 200;
204                         properties: "height,width,anchors.rightMargin,anchors.topMargin,opacity,contentY";
205                     }
206                 }
207             ]
208         }
209     }
210 }

3、卡牌效果

    示例代码可以直接放在qml文件中使用qmlscene.exe来预览

 1 import QtQuick 2.6
 2 
 3 Rectangle {
 4     id: root;
 5     width: 480;
 6     height: 300;
 7 
 8     PathView
 9     {
10         anchors.fill: parent;
11 
12         delegate: flipCardDelegate;
13         model: 100;
14 
15         path: Path{
16             startX: root.width / 2;
17             startY: 0
18 
19             PathAttribute { name: "itemAngle"; value: -45.0; }
20             PathAttribute { name: "itemScale"; value: 0.5; }
21             PathAttribute { name: "itemZ"; value: 0; }//属性值附加到代理上面
22             PathLine { x: root.width/2; y: root.height*0.4; }//路径元素定义
23             PathPercent { value: 0.48; }//控制两个元素之间的路径所占百分比
24             PathLine { x: root.width/2; y: root.height*0.5; }
25             PathAttribute { name: "itemAngle"; value: 0.0; }
26             PathAttribute { name: "itemScale"; value: 1.0; }
27             PathAttribute { name: "itemZ"; value: 100 }
28             PathLine { x: root.width/2; y: root.height*0.6; }
29             PathPercent { value: 0.52; }
30             PathLine { x: root.width/2; y: root.height; }
31             PathAttribute { name: "itemAngle"; value: 45.0; }
32             PathAttribute { name: "itemScale"; value: 0.5; }
33             PathAttribute { name: "itemZ"; value: 0; }
34         }
35 
36         pathItemCount: 17;//可见元素数目
37 
38         preferredHighlightBegin: 0.5;
39         preferredHighlightEnd: 0.5;
40     }
41     Component{
42         id: flipCardDelegate;
43 
44         Rectangle{
45             id: wrapper;
46 
47             width: 64;
48             height: 64;
49             antialiasing: true;//反锯齿
50 
51             //以上是关于qml基础学习 模型视图的主要内容,如果未能解决你的问题,请参考以下文章

来自模型的 QML 树视图

将 qml 信号连接到 Qt

如何在 QML 中进行基于状态的模型更改

26.Qt Quick QML-RotationAnimationPathAnimationSmoothedAnimationBehaviorPauseAnimationSequential(代码片段

如何防止在背面片段导航上再次设置视图模型

向 QAbstractListModel 子类添加新行时,QML 视图不会更新