标签:qml qt on android qt quick javascript
在《Qt on Android:Qt Quick 简介》中我们提到 QML 语法和 Json 类似,请参考《Qt on Android: http下载与Json解析》查看 Json 语法。当然这里我们是期望从零开始也能学会 QML ,所以呢,你也可以直接往下看。
QML 文件的后缀是 qml ,其实就是个文本文件。下面是 一个简单的 QML 文件:
import QtQuick 2.0 import QtQuick.Controls 1.1 import QtQuick.Dialogs 1.1 import an.qt.ImageProcessor 1.0 import QtQuick.Controls.Styles 1.1 Rectangle { width: 320; height: 480; color: "#121212"; Image { source: "images/IMG_001.jpg"; anchors.centerIn: parent; } }
Rectangle{ } 语句,定义了一个类型为 Rectangle 的对象。如果你看了《Qt on Android: http下载与Json解析》一文中有关 Json 的语法描述,应该已经知道对象要用一对花括号来描述。没错, QML 里也是这样,不过呢,花括号前要写上对象的类型。就这么简单!
示例 QML 文档中有两个对象,一个是 Rectangle ,一个是 Image 。
在花括号之间,是对象的属性描述(还可以有其它的,后面再说),属性是以 "property: value" 形式指定的,这点和 Json 一样。如你所见, Rectangle 对象有 width 、 color 等属性。
属性可以分行书写,此时语句后可以不要 ";" 号,不过笔者建议 C++ 程序猿都加上 ";" ,这会避免你患上精神分裂症。当然,也可以把多个属性写在一行内,多个属性之间必须以 ";" 分割。如下所示:
Rectangle { width: 320; height: 480; color: "#121212"; }我强烈建议你不要这么干!除非有代码意外的原因,比如排版需要,比如老板觉得你代码行数太多……
在《Qt on Android:Qt Quick 简介》中笔者已经提到, QML 支持 JavaScript 表达式。比如你可以这样改写 Rectangle 对象的宽、高属性:
Rectangle { width: 23*10; height: 6*80; color: "#121212"; }
Button { text: "Quit"; style: ButtonStyle { background: Rectangle { implicitWidth: 70; implicitHeight: 25; border.width: control.activeFocus ? 2 : 1; } } }
另外,慧眼如你,可能已经注意到,上面的表达式中我使用了 "control.activeFocus" ,没错,在表达式中可以引用其它对象及其属性。当你这么做的时候,待赋值的属性就和你所引用的对象的那个属性建立了关联,当被引用属性发生变化时,表达式的值会重新计算,而待赋值的属性也会变化。
也许你心中已经有了疑问:如何引用一个对象呢?答案是:通过对象的 id 值来引用一个对象。看这里:
Rectangle { width: 320; height: 480; Button { id: openFile; text: "打开"; anchors.left: parent.left; anchors.leftMargin: 6; anchors.top: parent.top; anchors.topMargin: 6; } Button { id: quit; text: "退出"; anchors.left: openFile.right; anchors.leftMargin: 4; anchors.bottom: openFile.bottom; } }
上面的示例中,退出按钮使用 id( openFile )引用了打开按钮。
我的乖呀,anchors 是什么东东……先别管它,下一篇会讲到。
在 QML 中,注释与 C++ 中一样,单行以 "//" 开始,多行以 "/*" 开始以 "*/" 结束。
注释是不被执行的,添加注释可对代码进行解释或者提高其可读性。注释同样还可用于防止代码执行,这对跟踪问题是非常有用的。
使用注释的示例 QML :
/* * the root element of QML */ Rectangle { width: 320; height: 480; Button { id: quit; text: "退出"; //use anchors to layout anchors.left: openFile.right; anchors.leftMargin: 4; anchors.bottom: openFile.bottom; //set z-order z: 1; } }
其实, QML 中的属性,就是我们非常熟悉的 C++ 中的成员变量……
属性名的首字母一般以小写开始,如我们看烦了的 width 属性。
如果属性名以多个单词表示,那么第二个及以后的单词,首字母大写。
可以在 QML 文档中使用的类型大概有三类:
我们先看 QML 语言提供的基本类型。
QML 支持的基本类型包括整型、实数型、布尔、字符串、颜色、列表等等。这些基本类型有些是和 JavaScript 语言的基本类型对应的。
还是之前的示例,修改了一下,通过注释标注了属性类型:
Rectangle { width: 320; //int height: 480; Button { id: quit; text: "退出"; //string anchors.left: openFile.right; anchors.leftMargin: 4; anchors.bottom: openFile.bottom; z: 1.5; // real visible: false; //bool } }
请使用 Qt 助手的索引模式,以"qml basic types " 为关键字检索,找到 QML Basic Types 页面来查看完整的类型列表和每个类型的详情。
Qt 的 QML 模块还未 QML 引入的很多 Qt 相关的类型,如 Qt 、 QtObject 、Component 、 Connections 、 Binding 等,请使用 Qt 助手检索 "qt qml qml types" 来了解。
之前在介绍表达式时提到了 id 属性,这里展开描述一下。
一个对象的 id 属性是唯一的,在同一个 QML 文件中不同对象的 id 属性的值不能重复。当给一个对象指定了 id ,就可以在其它对象或脚本中通过 id 来引用该对象。在“表达式”一节中我们已经演示了如何通过 id 来引用一个对象。
请注意, id 属性的值,首字符必须是小写字母或下划线并且不能包含字母、数字、下划线以外的字符。
列表属性类似于下面这样:
Item { children:[ Image{}, Text{} ] }
[ "name":"zhangsan", { "age":30, "phone":"13588888888", "other": ["xian", null, 1.0, 28] } ]
值得注意的是,列表内只能包含 QML 对象,不能包含任何基本类型(如整型、布尔型)。这点与 Json 是不一样的。下面是访问列表的示例:
Item { children:[ Text{ text: "textOne"; }, Text{ text: "textTwo"; } ] Component.onCompleted:{ for (var i = 0; i < children.length; i++) console.log("text of label ", i, " : ", children[i].text) } }
如果你一个列表内只有一个元素,也可以省略方括号。如下所示:
Item { children:Image{} }
不过笔者还是建议你始终使用方括号,哪怕其中只有一个元素。
有没有什么问题?有就要说啊,闷在心里会憋坏自己的。好吧,你不说我就说了。在我们访问列表的示例中出现了一个新的内容,Component.onCompleted :{} ,这是什么东东呢?接下来我们就来讲它。
信号处理器,其实等价于 Qt 中的槽。但是我们没有看到类似 C++ 中的明确定义的函数……没错,就是这样,你的的确确只看到了一对花括号!对啦,这是 JavaScript 中的代码块。其实呢,你可以理解为它是一个匿名函数。而 JavaScript 中的函数,其实具名的代码块。函数的好处是你可以在其它地方根据名字调用它,而代码块的好处是,除了定义它的地方,没人能调用它,一句话,它是私有的。代码块就是一系列语句的组合,它的作用就是使语句序列一起执行。
让我们回头再看信号处理器,它的名字还有点儿特别,一般是 on{Signal} 这种形式。比如 Qt Quick 中的 Button 元素有一个信号 clicked() ,那么你要可能会写出这样的代码:
Rectangle { width: 320; height: 480; Button { id: quit; text: "退出"; anchors.left: parent.left; anchors.leftMargin: 4; anchors.bottom: parent.bottom; anchors.bottomMargin: 4; onClicked: { Qt.quit(); } } }
你看到了,当信号是 clicked() 时,信号处理器就命名为 onClicked 。就这么简单,以 on 起始后跟信号名字(第一个字母大写)。
在某些情况下使用一个 ‘.‘ 符号或分组符号把相关的属性形成一个逻辑组。分组属性可写以下这样:
Text { font.pixelSize: 18; font.bold: true; }
Text { font { pixelSize: 12; bold: true; } }
属性真难搞!到现在还没讲完,不但你烦了,我也快坐不住了。我保证,这是最后一个要点了,不过也是最复杂最难以理解的属性了。对于这种玩意儿,我一向的做法时,不能理解的话就接受,你就当它生来如此,存在即合理,只要学会怎么用它就 OK 了。
在 QML 语言的语法中,有一个附加属性(attached properties)和附加信号处理器(attached signal handlers)的概念,这是附加到一个对象上的额外的属性。从本质上讲,这些属性是由附加类型(attaching type)来实现和提供的,它们可能被附加到另一种类型的对象上。附加属性与普通属性的区别在于,对象的普通属性是由对象本身或其基类(或沿继承层级向上追溯的祖先们)提供的。
举个例子,下面的 Item 对象使用了附加属性和附加信号处理器:
import QtQuick 2.0 Item { width: 100; height: 100; focus: true; Keys.enabled: false; Keys.onReturnPressed: console.log("Return key was pressed"); }
最后说下 Keys 对象,它是 Qt Quick 提供的,专门供 Item 处理按键事件的对象。它定义了很多针对特定按键的信号,比如上面的 onReturnPressed ,还定义了更为普通的 onPressed 和 onReleased 信号,一般地,你可以使用这两个信号来处理按键(请对照 Qt C++ 中的 keyPressEvent 和 keyReleaseEvent 来理解)。它们有一个名字是 event 的 KeyEvent 参数,包含了按键的详细信息。如果一个按键被处理, event.accepted 应该被设置为 true 以免它被继续传递。
下面是使用 onPressed 信号的一个示例,它检测了左方向键:
Item { anchors.fill: parent; focus: true; Keys.onPressed: { if (event.key == Qt.Key_Left) { console.log("move left"); event.accepted = true; } } }
好啦,关于 QML 语言的基础性介绍就到这里,相信现在你已经可以看懂简单的 QML 文档了。有的同学可能又疑问了,这节还有一些东东只见用不见讲啊,比如 Rectangle / Text / Image / Item / Button / Component / Qt 等等,抱歉,现在只能揣着糊涂装明白了,下一篇我们会讲这些东西。
Qt on Android:QML 语言基础,布布扣,bubuko.com
标签:qml qt on android qt quick javascript
原文地址:http://blog.csdn.net/foruok/article/details/28634543