一本QML教学书, 基于QT5 : https://github.com/cwc1987/QmlBook-In-Chinese


QML介绍

QML 是一种基于 JavaScript 的声明式语言, 而且源码中为一个对象树结构.
在QT5下, 可使用Bin目录下的 qmlscene 程序进行直接运行符合QML语法的 *.qml 文件,

  1. import QtQuick 2.1
  2. import QtQuick.Window 2.0
  3. Window {
  4. visible: true
  5. width: 360
  6. height: 360
  7. MouseArea {
  8. anchors.fill: parent
  9. onClicked: {
  10. Qt.quit();
  11. }
  12. }
  13. Text {
  14. text: qsTr("Hello World")
  15. anchors.centerIn: parent
  16. }
  17. }

一个 QML 文档分为 importdeclaration 两部分。前者用于引入文档中所需要的组件(有可能是类库,也可以是一个 JavaScript 文件或者另外的 QML 文件);后者用于声明本文档中的 QML 元素。
每一个 QML 有且只有一个根元素,类似于 XML 文档。这个根元素就是这个 QML 文档中定义的 QML 元素

QML学习 - 图1


  1. QML 是一种声明语言,用于描述程序界面。

  2. QML 将用户界面分解成一块块小的元素,每一元素都由很多组件构成。

  3. QML 定义了用户界面元素的外观和行为;更复杂的逻辑则可以结合 JavaScript 脚本实现。这有点类似于HTML 和 JavaScript 的关系,前者用来显示界面,后者用来定义行为。

  4. QML 最简单的元素关系是层次关系。子元素处于相对于父元素的坐标系统中。也就是说,子元素的 x 和 y 的坐标值始终相对于父元素。

定义变量(property)

一般用于导出对象和变量, 或者定义一个新的变量
自定义 QML 属性: property <type> <name> : <value>
声明属性的别名: property alias <name> : <reference>

比如:

导出内部对象的名称 property alias text: input.text
导出内部对象 property alias input: input
定义一个变量 property int colorIndex: Math.floor(Math.random()*3)
定义一个变量数组 property variant colorArray: ["#00bde3", "#67c111", "#ea7025"]

如果你想要完整的导出TextInput对象的元素,你可以使用 property alias input: input 来导出这个元素。第一个input是属性名字,第二个input是元素id。


键值对

在使用属性键值 X,Y 或者 Width,Height 时, 需同时定义在一行, 分行时, 容易出错

  1. x: 112 ; y: 12
  2. width: 76; height: 96

渐变色

  1. gradient: Gradient {
  2. GradientStop { position: 0.0; color: "lightsteelblue" } // 渐变的开始
  3. GradientStop { position: 1.0; color: "slategray" } // 渐变的结束
  4. }
  5. // 一个矩形框如果没有width/height(宽度与高度)将不可见。
  6. // 如果你有几个相互关联width/height(宽度与高度)的矩形框,
  7. // 在你组合逻辑中出了错后可能就会发生矩形框不可见,请注意这一点。

定位

注意:
高级的大数据模型处理和使用动态代理的动态视图会在模型与视图(model-view)章节中讲解。当有一小部分的静态数据需要显示时,使用重复元素是最好的方式

均由 spacing`` 字段进行间隔设置

column(列, 在一列中布局行)

QML学习 - 图2

row(在一行中布局列)

QML学习 - 图3

Grid(栅格)

QML学习 - 图4

Flow(流)

QML学习 - 图5

Repeater(自动重复控件布局)

QML学习 - 图6


文本输入 (TextInput - TextEdit)

TextInput 允许使用正则表达式验证器来限制输入和输入掩码模式的设置
TextEdit 支持多行输入, 不支持文本输入监测限制

焦点(focus - focus scope)

一个焦点区域(focus scope)定义了如果焦点区域接收到焦点,它的最后一个使用focus:true的子元素接收焦点,它将会把焦点传递给最后申请焦点的子元素。我们创建了第二个版本的TLineEdit组件,称作TLineEditV2,使用焦点区域(focus scope)作为根元素。

QML学习 - 图7


ListView(列表框)

  1. // 裁剪显示, 允许出现上下临界元素显示一半的情况
  2. clip: true
  3. // 默认值, 在末尾可继续拖拽,自动回弹
  4. boundsBehavior: Flickable.DragAndOvershootBounds
  5. // 拖拽至末尾后, 无法继续拖拽
  6. boundsBehavior: Flickable.StopAtBounds
  7. // 每次滚动之后, 顶部会对齐到整个元素, 不会显示一半
  8. snapMode: ListView.SnapToItem
  9. // 每次滚动之后, 顶部会停止在第一个可见元素
  10. snapMode: ListView.SnapOneItem
  11. // 链表视图的方向由属性orientation控制。
  12. // 它能够被设置为默认值ListView.Vertical或者ListView.Horizontal。
  13. orientation: ListView.Vertical
  14. orientation: ListView.Horizontal
  15. // 可以通过设置layoutDirection属性来控制元素顺序方向,
  16. // 它可以设置为Qt.LeftToRight或者Qt.RightToLeft。
  17. layoutDirection: Qt.LeftToRight
  18. layoutDirection: Qt.RightToLeft

高亮显示

  1. highlight: highlightComponent
  2. focus: true
  3. Component {
  4. id: highlightComponent
  5. Rectangle {
  6. width: ListView.view.width
  7. // width: lstView.view.width
  8. color: "lightGreen"
  9. }
  10. }
  11. // 高亮与元素距离不相关
  12. // highlightRangeMode: ListView.NoHighlightRange
  13. // 高亮, 且默认显示第一个为当前选中
  14. // highlightRangeMode: ListView.StrictlyEnforceRange
  15. // 默认下速度被设置为每秒400像素,动作持续时间为-1
  16. // highlightMoveSpeed // 控制每项元素之间切换速度
  17. // highlightMoveDuration // 控制移动时, 运动持续时间
  18. // highlightResizeSpeed //
  19. // highlightResizeDuration
  20. // 设置高亮的移动, 不自动控制, 需要自行实现Bahavior
  21. //highlightFollowCurrentItem: false

QML学习 - 图8

使用 Behavior 自行实现高亮移动

  1. Component {
  2. id: highlightComponent
  3. Item {
  4. width: ListView.view.width
  5. height: ListView.view.currentItem.height
  6. y: ListView.view.currentItem.y
  7. Behavior on y {
  8. SequentialAnimation {
  9. PropertyAnimation{ target: highlightRectangle; property: "opacity"; to: 0; duration: 150 }
  10. NumberAnimation { duration: 1 }
  11. PropertyAnimation{ target: highlightRectangle; property: "opacity"; to: 1; duration: 150 }
  12. }
  13. }
  14. Rectangle {
  15. id: highlightRectangle
  16. anchors.fill: parent
  17. color: "lightGreen"
  18. }
  19. }
  20. }

Tips

鼠标响应无效

应该鼠标响应在前, 然后对象申明定义在后, 否则会出现鼠标点击无效的状况. 暂未知具体原因

有一个解释, 没有看懂:

在代码中先出现的元素有更低的堆叠顺序(叫做z顺序值z-order),如果你点击火箭1足够多次,你会看见火箭1移动到了火箭2下面。z轴顺序也可以使用元素对象的z-property来控制。

由于火箭2后出现在代码中,火箭2将会放在火箭1上面。这同样适用于MouseArea(鼠标区域),一个后出现在代码中的鼠标区域将会与之前的鼠标区域重叠,后出现的鼠标区域才能捕捉到鼠标事件。

既然后定义的会覆盖, 为什么需要给MouseArea 定义在前边才能生效呢? 暂未知具体原因
以下分别为可以点击生效的代码 和 不可生效的代码:
QML学习 - 图9QML学习 - 图10

在我个人的理解中: 对象未出现, 无法直接使用, 所以应该后定义鼠标事件, 但在实际情况中 后定义的鼠标事件并未生效, 暂未知具体原因

QML 同目录下的模块使用

注意: 被使用的模块所在文件的文件名, 首字母必须大写