QtQuick桌面应用程序开发指导 3)达到UI而功能_B 4)动态管理Note物_A
3.2 把Page Item和Marker Item绑定
之前我们实现了PagePanel组件, 使用了三个state来切换Page组件的opacity属性; 这一步我们会使用Marker和MarkerPanel组件来实现页面导航;
在原型阶段, MarkerPanel组件十分简单, 没有不论什么功能; 它使用了Repeater类型来产生三个QML Item以及Marker组件作为delegate;
MarkerPanel应该存储当前激活的marker(标记), 即那个被用户点击的marker; 基于MarkerPanel中激活的marker, PagePanel会更新它的state属性; 我们须要将PagePanel的state属性和MarkerPanel新的属性--持有当前激活marker的属性绑定起来;
在MarkerPanel中定义一个string属性--activeMarker;
// MarkerPanel.qml
1
2
3
4
5
6
7
|
Item id: width: // // property "personal" //... |
我们能够把一个markerid值存储起来, 用来唯一地识别marker item; 这样, activeMarker会持实用户所点击的marker item的markerid的值,
依据model, Repeater元素能够产生三个marker item, 因此我们能够使用一个model来存储markerid值, 然后在Repeater中使用;
// MarkerPanel.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
Item id: width: // // property "personal" // property { "personal" }, { "fun" }, { "work" } ] Column id: anchors.fill: spacing: Repeater // model: delegate: id: // // // //MouseArea //anchors.fill: onClicked: //} } } } } |
上述代码中我们在onClicked signal handler中设置了 activeMarker属性; 这意味着我们已经在Marker组件中定义了一个clicked() signal来通知用户的鼠标点击事件;
// Marker.qml
1
2
3
4
5
6
7
8
9
10
11
|
Item id: width: signal MouseArea id: anchors.fill: // onClicked: } } |
眼下我们以后有了PagePanel组件使用state属性来管理page, 让MarkPanel组件能够识别激活的marker, 因此, 切换各个page的可见性能够通过改变page的opacity属性来做到;
来看看如何使用 activeMarker属性来相应地更新PagePanel的state;
在main.qml里面, 已经有了Page item和 MarkerPanel定位好了, 我们会创建以及使用PagePanel item而不是各自使用anchor定位;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
// MarkerPanel id: width: anchors.topMargin: anchors right: top: bottom: } } //... // PagePanel id: // // state: anchors right: left: top: bottom: leftMargin: rightMargin: topMargin: bottomMargin: } } |
上面代码中, 我们能够看到QML的 property binding特性, 能够把state属性和activeMarker属性绑定起来; 这样不论activeMarker通过用户操作获得了什么值, 同样的值会被分配给PagePanel的state属性, 这样就能开关各个page的可见性了;
下一步
给出如何使用使用图形来强化UI的细节;
3.3 加入graphics(图形)
由于QML的特性, 开发和设计全然能够一起紧密工作, 贯彻整个开发生命期; 现在, 使用graphics让用户体验有了非常大的不同, 这也是程序让用户感受到的地方;
QML鼓舞在UI实现过程中尽可能地使用graphics; 使用QML让图形设计和开发之间的协作更easy, 设计能够立马在主要的UI元素上測试graphics; 这帮助设计来理解在开发新的组件时, 程序猿会须要什么, 这也让程序的UI更有吸引力并且某种程度上更易维护;
3.3.1 给组件设置背景图片
BorderImage类型推荐使用的情况是: 在你想要把一个图片scale(按比例拉伸), 但它的border(边界)保持不变的时候; 这样的类型的一个好的用例(use case)是在QML item上有阴影效果的背景图片; 你的item可能会在某些时刻scale可是须要保持corners(四角)不变;
来看下如何在组件中将BorderImage设置成背景;
// PagePanel.qml
1
2
3
4
5
6
7
8
9
10
11
|
//... BorderImage id: // anchors.fill: source: "images/page.png" // // border.left: border.right: } |
// Note.qml
1
2
3
4
5
6
7
|
BorderImage id: anchors source: "images/personal_note.png" border.left: border.right: } |
Warning: 注意BorderImage类型要以正确的次序在组件里面使用, 由于实现的次序定义了显示的顺序; 具有同样 z值的item显示的次序是按它们被声明的次序决定的; 很多其它细节參考stack ordering of items-- z property;
当这些item都在MarkerPanel组件中创建的时候, 如何才是给Marker item设置背景的最佳方案--这个方法已经在MarkerPanel中展现了;
这里有个markerData list, 把它作为model给Repeater来创建Marker item, 当一个marker item被点击的时候, 设置markerid作为activeMarker; 我们能够扩展markerData, 存储一个图像的的url路径, 使用Image类型作为Marker组件的顶层类型;
// Marker.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// // // Image id: // signal // MouseArea id: anchors.fill: // onClicked: } } |
这样就能够增强MarkerPanel组件;
// MarkerPanel.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//... // property { "images/personalmarker.png" , "personal" }, { "images/funmarker.png" , "fun" }, { "images/workmarker.png" , "work" } ] Column id: anchors.fill: spacing: Repeater // model: delegate: id: // // // source: // // // onClicked: } } } |
上述代码中, 能够看到Marker item的source属性是怎样绑定到markerData model的image值的;
我们使用了BorderImage类型来为NoteToolbar组件设置背景, 也作为main.qml的顶层类型;
Note 关于图像的border margins, 以及图像的怎样anchor和align(对齐), 要和graphics设计讨论清楚;
MarkerPanel组件看起来是这种:
然后来看看如何在原型阶段使用graphics依照设计来增强toolbar;
3.3.2 创建Tool组件
基于代码重用考虑, 定义一个新组件给toolbar中的New Note和Clear All工具使用; 这是为什么我们已经实现了一个Tool组件, 使用Image类型作为顶层类型, 处理鼠标点击事件;
Image类型经经常使用作UI元素自身, 不论是静态的或是动绘图像; 它会按像素布局, 能够非常好地依照设计需求来定义;
// Tool.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// Image id: // signal // // MouseArea anchors.fill: // onClicked: } } |
如今用Tool组件来创建toolbar; 我们从原型阶段改动代码, 用Tool item取代Rectangle元素;
//main.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//... // Rectangle anchors.fill: color: "white" opacity: radius: border "#600" ; } // // Column // id: spacing: anchors top: left: bottom: topMargin: bottomMargin: leftMargin: } // Tool id: source: "images/add.png" } // Tool id: source: "images/clear.png" } } |
如今我们给我们的组件设置了全部的graphics, 程序应该有了更吸引人的外观和很多其它定义好的UI了;
下一步
下一章具体介绍怎样动态地创建和管理Note item以及怎样在本地数据库存储它们;
---3End---
CHAPTER4 动态管理Note对象
我们眼下看到的QML是一个很强大的声明性(declarative)语言, 和JavaScript组合使用让它更强大; QML不仅提供了 inline JavaScript, 并且还能够把整个JavaScript库导入到文件里;
NoteApp的核心功能是能够让用户去创建, 改动和删除note, 可是程序应该也要自己主动存储note, 无需提示;
这一章会指导怎样使用JavaScript来给QML代码加入逻辑, 实现本地存储--Qt Quick Local Storage
本章主要主题:
- 使用JavaScript实现动态对象管理的功能;
- 怎样使用 Qt Quick Database API 进行本地数据存储;
4.1 创建和管理Note Item
用户应该随时能够创建和删除note, 这意味着我们的代码应该能够动态地创建和删除Note item; 有多种方式创建和管理QML对象; 其实, 我们已经使用一种--Repeater类型; 创建一个QML对象意味着在创建组件的实例之前, 组件必需要被创建和载入起来;
QML对象能够通过 createObject(Item parent, object properties) JavaScript方法在组件上创建; 很多其它细节參考 Dynamic Object Management in QML http://qt-project.org/doc/qt-5/qtqml-javascript-dynamicobjectcreation.html
4.1.1 Note对象的动态创建
我们知道一个Note item是属于Page组件的, 它负责note对象的创建, 也会从数据库中读取笔记;
如前面所说, 首先载入Note组件:
// Page.qml
1
2
3
4
5
6
|
//... // Component id: Note } |
如今我们来定义一个Javascript方法, 创建QML Note对象; 创建QML对象的时候, 必须保证一个參数是这个对象的parent; 在Page组件中持有一个Note item容器(container)是个管理note对象的好主意, 这样我们能够在数据库中保存这些note;
// Page.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//... // Item // function newNoteObject(args) // // // var note if (note null ) console.log( "note ) } |
在前面显示的代码中, 我们看到一个新的 note item对象是如何在 newNoteObject()方法中创建的; 新建的 note对象隶属于container item;
如今我们要在toolbar上的new note tool被按下的时候调用这种方法, toolbar在main.qml中; 因为PagePanel组件知道当前可见的page item, 我们能够在PagePanel中创建一个新的属性来存储那个page;
// PagePanel.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
//... // property // states: // State name: "personal" PropertyChanges target: opacity:1.0 restoreEntryValues: true } PropertyChanges target: currentPage: explicit: true } }, State name: "fun" PropertyChanges target: opacity:1.0 restoreEntryValues: true } PropertyChanges target: currentPage: explicit: true } }, State name: "work" PropertyChanges target: opacity:1.0 restoreEntryValues: true } PropertyChanges target: currentPage: explicit: true } } ] |
我们改动了三个state来给currentPage属性设置合适的值;
在main.qml中, 看看在new note tool被点击的时候如何调用方法来创建新的note对象;
// main.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// Column id: spacing: anchors top: topMargin: } // Tool id: source: "images/add.png" // // onClicked: } |
4.1.2 删除Note对象
删除Note对象是个更直接的过程, 由于QML item类型提供了一个JavaScipt方法--destroy() http://qt-project.org/doc/qt-5/qtqml-javascript-dynamicobjectcreation.html#deleting-objects-dynamically
; 由于我们已经有一个container item的children是Note item, 我们能够简单地对children逐个地调用 destroy;
在Page组件上, 定义一个方法来为我们运行操作:
// Page.qml
1
2
3
4
5
6
7
|
//... // // function clear() for ( var i=0; container.children[i].destroy() } |
在main.qml文件里, 我们在clear tool被按下时调用 clear()方法:
1
2
3
4
5
6
7
|
//... // Tool id: source: "images/clear.png" onClicked: } |
为了让用户能够独立地删除每个note, 我们在NoteToolbar组件中为Note组件加入了一个tool; 能够使用签名实现的Tool组件:
// Note.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//... // NoteToolbar id: height: anchors // drag.target: // Tool id: source: "images/delete.png" onClicked: } } |
下一步
关于怎样在本地数据库存储note item的具体步骤;
4.2 从数据库存储和读取数据
眼下我们实现了NoteApp的功能: 实时地创建和管理note item;
这里我们会了解在本地数据库存储note的具体实现; QML提供了一个简单的 Qt Quick Local Storage API, 使用SQLite数据库来实现我们想要的功能;
首选的方式是在NoteApp程序启动的时候从数据库读取note, 然后在程序关闭的是保存它们; 用户不会收到提示;
4.2.1 定义数据库
NoteApp的数据库非常easy; 它仅仅有一个table--note table, 包括我们所保存的note的信息;
看一下Table的定义, 让我们了解下Note组件的哪些属性或哪些新的数据应该被引入:
x和y是每一个QML item都有的几何属性; 从Note item获得这些值非常easy; 这些值会用来粗糙你note在page中的位置; noteText是note的实际文字, 我们能够从Note组件中的Text元素中获取它们, 我们应该定义一个alias(别名_)--noteText; noteId和markerId是每一个note item都该有的标识符; noteId是一个唯一的标识符, 数据库须要用到, markerId用来标识note item属于哪一个page; 因此我们会在Note组件里面加入两个新的属性;
// Note.qml
1
2
3
4
5
6
7
8
9
10
11
12
|
Item id: width: property property property //... // TextEdit id: //... |
考虑到Page组件负责创建Note item, 它应该也知道Note和哪个markerId相关联; 当一个新的Note item创建出来(不是从数据库读取), Page应该设置好Note的markerId属性;
使用一个JavaScript的 helper方法:
// Page.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Item id: // // property // // // function newNote() // // newNoteObject( "markerId" : } //... |
先前在main.qml中, 我们使用了 newNoteObject()方法, 但就如前面解释的, 我们须要用newNote()方法取代它来达到目的;
如今每一个Page组件有个markerId属性, 能够在Note item被创建的时候设置markerId; 我们必须保证page的markerId属性在Page item在PagePanel组件中创建的时候就被设置了;
// PagePanel.qml
1
2
3
4
5
|
//... // Page "personal" } Page "fun" } Page "work" } |
眼下我们保证的:
- 从相应的关系数据库[relational database http://en.wikipedia.org/wiki/Relational_database ]得到的note和page之间的关系是正确的;
- 每一个Note item有一个唯一的ID, ID属于page, 能够识别marker ID;
- 这些属性值要被正确设置;
以下来读取和存储笔记;
---TBC---
QtQuick桌面应用程序开发指导 3)达到UI而功能_B 4)动态管理Note物_A的更多相关文章
- QtQuick桌面应用程序开发指南 4)动态管理Note对象_B 5)加强外观 6)许多其他的改进
4.2.2 Stateless(不管状态)JavaScript库 为了让开发轻松点, 使用一个JavaScript接口来和数据库交互是个好主意, 它在QML中提供了方便的方法; 在QtCreator中 ...
- Electron与WEB桌面应用程序开发及其它
这几天在构思项目,研究了一下Electron,记录下来. 说起WEB桌面程序,当前最火的就是Electron了. Electron的架构用一句话总结,就是一个main.js进程加上一个或数个chrom ...
- c#桌面应用程序开发--登陆窗口
一.显示登陆窗口 应用程序入口点为Main方法,因此在Main方法中创建登陆窗体. 1)创建登陆窗体(登陆窗体UI已提前创建好); 2)显示窗体,以模式对话框的形式显示,并赋值给result; 3)判 ...
- mpvue小程序开发之 集成第三方UI框架Vant Weapp UI
集成进第三方的UI框架其实很简单 这里把vant-weapp的dist目录重命名为vant-weapp放在项目根目录的static文件夹下: 在src文件夹下,即我们写vue代码的位置,正在编写的页面 ...
- 微信小程序开发 -- 点击右上角实现转发功能
// 在page的js文件中加入以下代码/** * 用户点击右上角分享 */ onShareAppMessage: function () { }
- 微信小程序开发 (资料汇总,谁还没被坑过?希望助你绕过一些坑)
最近帮人家做一个微信小程序,刚好想熟悉一下.由于牵扯到多用户使用系统,以及数据共享,所以自然架构选择了,客户端和服务器的方式. 后台服务器是windows server,后台程序是.Net WebA ...
- 微信小程序开发(3) 热门电影
在这篇微信小程序开发教程中,我们将介绍如何使用微信小程序开发热门电影及预览功能. 本文主要分为两个部分,小程序主体部分及电影主页和详情页页面部分 一.小程序主体部分 一个小程序主体部分由三个文件组成, ...
- QtQuick桌面应用开发指导 1)关于教程 2)原型和设计 3)实现UI和功能_A
Release1.0 http://qt-project.org/wiki/developer-guides Qt Quick Application Developer Guide for Desk ...
- electron之Windows下使用 html js css 开发桌面应用程序
1.atom/electron github: https://github.com/atom/electron 中文文档: https://github.com/atom/electron/tree ...
随机推荐
- Zoj 3545 Rescue the Rabbit(ac自己主动机+dp)
标题效果: 鉴于DNA有一个正确的顺序值.请构造一个长度I的DNA在这个序列使DNA正确的顺序值极大.它被认为是负的输出噼啪. .. IDEAS: 施工顺序是,ac己主动机上走,求最大要用到dp dp ...
- Blend4精选案例图解教程(三):一键拖拽
原文:Blend4精选案例图解教程(三):一键拖拽 拖拽效果,常规实现方法是定义MoveLeftDwon.MoveLeftUp.MouseMove事件,在Blend的世界里,实现对象的拖拽,可以不写一 ...
- 【原创】编写多线程Python爬虫来过滤八戒网上的发布任务
目标: 以特定语言技术为关键字,爬取八戒网中网站设计开发栏目下发布的任务相关信息 需求: 用户通过设置自己感兴趣的关键字或正则表达式,来过滤信息. 我自己选择的是通过特定语言技术作为关键字,php.j ...
- Autodesk FBX SDK Program 中文 (二)
这是Autodesk FBX SDK学习笔记第二篇.下面部分汉字翻译自Autodesk FBX SDK Program.翻译人:有道翻译. 上一篇讲了一些FBX SDK的基本操作.创建FbxManag ...
- 当用户登录,经常会有实时的下拉框,例如,输入邮箱,将会@qq.com,@163.com,@sohu.com
如图所示, 码,如以下:<input id="user_sn" class="loginInput" name="user_sn" t ...
- jquery 判断当前上传文件大小限制上传格式 搭配thinkphp实现上传即预览(模拟异步上传)
在web开发中,最纠结的一项就是文件上传,最近由于项目需要前后摸索了四天在这里分享给大家.如有不足,望指出!! 前台:jquery.easyui.html 后台:thinkphp 主要涉及语言:jqu ...
- PHPSingleton模式的例子
在这篇文章中PHPSingleton模式的解释不一定好!仅举它的一个例子.其目的是为了让自己通过一个例子来加深对Singleton模式的理解!这里,以供参考! 单例:能够简单的理解是通过一个类,仅仅能 ...
- 《Qt on Android核心编程》夹
china-pub在售前,售中环节退房,折扣低! 有朋友想看看<Qt on Android核心编程>的文件夹,So-- 文件夹 <Qt on Android核心编程>文 ...
- Windows下效率必备软件
AutoHotKey: 神器!神器!神器!当然也得看使用者咯(^__^) 嘻嘻…… Listary: 本地搜索神器,当然还有别的作用,More&More. Launchy : 快速启动安装的应 ...
- STL内存分配
STL内存创建 Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源 1. Stl内存创建基类模板__malloc_alloc_tem ...