【学习笔记】QML 语法基础

本文为翻译,原文链接: QML Syntax Basics

Qt 版本:5.12

QML 是一种多范式语言,可以根据对象的属性以及它们如何关联和响应其他对象的变化来定义对象。与纯命令式代码相比,属性和行为的变化是通过一系列逐步处理的语句来表达的,QML 的声明式语法将属性和行为的变化直接集成到单个对象的定义中。在需要复杂的自定义应用程序行为的情况下,这些属性定义可以包含命令式代码。

QML 源代码一般由引擎通过 QML 文档加载,QML 文档是 QML 代码的独立文档。这些可用于定义 QML 对象类型,然后可以在整个应用程序中重复使用。请注意,类型名称必须以大写字母开头,才能在 QML 文件中声明为 QML 对象类型。

也就是说,我们可以将 QML 理解为一种脚本语言,用来编写图形界面各组件的属性(例如位置、颜色)和各组件点击之后的发生的事件(响应)。同时,.qml 文件名如果以大写字母开头,可以作为一个类型。并在同一目录下的其他 .qml 文件中作为类型调用。

Import Statements

有时候我们需要导入其他的 qml 文档(就类似于 Python 导入模块一样)。我们有以下三种方式:

方式一

import <ModuleIdentifier> <Version.Number> [as <Qualifier>]

ModuleIdentifier 就是模块的标识符,比如说 QtQuick 或者是 QtQuick.LocalStorage

Version.Number 就是版本号,比如说 2.0

后面的 as <Qualifier> 是可选的,为了就是用一个更加方便的名称替代原来的模块名

举几个栗子:

import QtQuick 2.0
import QtQuick.LocalStorage 2.0 as Database

方式二

第二种方式就是用 QML 文档的相对目录来导入。

例如

import "../privateComponents"

方式三

通过 JavaScript 文件

import "somefile.js" as Script


对象声明

在语法上,QML 代码块定义了要创建的 QML 对象树。对象是使用对象声明来定义的,这些声明描述了要创建的对象的类型以及要赋予对象的属性。每个对象还可以使用嵌套对象声明来声明子对象。

对象声明由其对象类型的名称组成,后跟一组花括号。然后在这些大括号内声明所有属性和子对象。

比如以下是这个完整的例子:

import QtQuick 2.0
Rectangle {
    width: 100
    height: 100
    color: "red"
}

这声明了一个 Rectangle 类型的对象,后跟一组包含为该对象定义的属性的花括号。 Rectangle 类型是 QtQuick 模块提供的一种类型,在这种情况下定义的属性是矩形的宽度、高度和颜色属性的值。 (这些属性由 Rectangle 类型提供,如 Rectangle 文档 中所述。)由于 Rectangle 类型是由 QtQuick 提供的,所以我们要先导入 QtQuick 2.0 或者其他版本。

如果一个对象定义只有少量的属性,可以像这样写在一行上,属性用分号分隔:

Rectangle { width: 100; height: 100; color: "red" }

此外,对象声明可以定义 子对象 ,如下所述。


子对象

任何对象声明都可以通过嵌套的对象声明来定义子对象。这样,任何对象声明都隐含地声明了一个对象树,该树可能包含任意数量的子对象。

例如,下面的 Rectangle 对象声明包括一个 Gradient 对象声明,该声明又包含两个 GradientStop 声明:

import QtQuick 2.0
Rectangle {
    width: 100
    height: 100
    gradient: Gradient {
        GradientStop { position: 0.0; color: "yellow" }
        GradientStop { position: 1.0; color: "green" }
}

当引擎加载这段代码时,它会创建一个以 Rectangle 对象为根的对象树;这个对象有一个 Gradient 子对象,它又具有两个 GradientStop 子对象。

但是请注意,这是 QML 对象树上下文中的父子关系,而不是视觉场景上下文中的父子关系。视觉场景中父子关系的概念由 QtQuick 模块中的 Item 类型提供,它是大多数 QML 类型的基本类型,因为大多数 QML 对象旨在进行视觉渲染。例如,Rectangle 和 Text 都是基于 Item 的类型,下面将 Text 对象声明为 Rectangle 对象的可视子对象:

import QtQuick 2.0
Rectangle {
    width: 200
    height: 200
    color: "red"
    Text {
        anchors.centerIn: parent
        text: "Hello, QML!"
}

当 Text 对象在上面的代码中引用它的父值时,它引用的是它的可视化父对象,而不是对象树中的父对象。在这种情况下,它们是一回事:在 QML 对象树的上下文以及视觉场景的上下文中,Rectangle 对象都是 Text 对象的父对象。然而,虽然可以修改 parent 属性以更改可视化父级,但无法从 QML 更改对象树上下文中对象的父级。

(另外,请注意,Text 对象已被声明,但并未将其分配给 Rectangle 的属性,这与之前将 Gradient 对象分配给矩形的渐变属性的示例不同。这是因为 Item 的 children 属性已设置为类型的默认属性以启用这种更方便的语法。)

有关具有 Item 类型的 visual parent 的概念的更多信息,请参阅 visual parent 文档。


注释

QML 中注释的语法类似于 JavaScript:

  1. 单行注释使用 //
  2. 多行注释使用 /* * /

如下:

Text {
    text: "Hello world!"    //a basic greeting