QML语法——基础篇

Qt Quick 为 Qt 引入了一门叫 QML(Qt Meta/Modeling Language)的脚本语言,它是 ECMAScript 标准的实现。所以 QML 语法是在 ECMAScript 语法的基础上实现的。

ECMAScript 语言的标准是由 Netscape、Sun、微软、Borland 等公司基于 JavaScript 和 JScript 锤炼、定义出来的。

ECMAScript 仅仅是一个描述,定义了脚本语言的所有属性、方法和对象。其他语言可以实现 ECMAScript 来作为功能的基础,正如 JavaScript 那样。这个实现又可以被扩展,包含特定于宿主环境的新特性,比如 QML 就引入了 Qt 对象系统中的信号与槽,还增加了动态属性绑定等非常有特色的新功能。

作为一种全新的编程语言,QML 有三个核心:

  • ECMAScript
  • Qt 对象系统
  • Qt Quick 标准库

本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓

一、语法

下面一个个来看 ECMAScript 的语法。(QML 是 ECMAScript 标准的实现,所以两者语法是基本一样的)

1. 区分大小写

与 C++ —样,变量、函数名、运算符以及其他一切东西都是区分大小写的,也就是说, 变量 area 和 Area 是不同的。

2. 弱类型

与 C++ 不同,ECMAScript 中的变量没有特定的类型,定义变量时只用 var 运算符,可以将它初始化为任意的值,你可以随时改变变量所存储的数据类型(实际上应当尽量避免这样做)。例如:

var i = 0
console.log(i)
i = "hello"
console.log(i)

尽管在语法上这么做没有问题,但好的编码习惯是一个变量始终存放相同类型的值。

3. 语句后的分号可有可无

C、C++、Java 等语言都要求每条语句以分号(;)结束。ECMAScript 则允许开发者自行决定是否以分号结束一行代码。如果没有分号,ECMAScript 就把这行代码的结尾看作该语句的结束(与 Lua、Python、Visual Basic 相似)。至于加不加分号,那就看自己的喜好了。下面两行代码的语法都是正确的:

var background = "white"
var i = 0

二、变量

在 ECMAScript 中使用 var 运算符声明变量,与 C++ 类似,变量名需要遵循一定的规则。

1. 变量声明

变量用 var 运算符加变量名来定义。例如:

var i = 0

在这个例子中,声明了变量 i 并把它初始化为 0。你也可以不初始化,在用到时再初始化。

一个 var 语句可以定义多个变量。例如:

var i = 0 , name = "j"

这个例子定义了变量 i,初始化为数字;还定义了变量 name,初始化为字符串。你看到了,这和 C++ 或 Java 不同,一个 var 语句定义的多个变量可以有不同的类型。

2. 变量命名规则

变量命名需要遵守两条简单的规则:

  • 第一个字符必须是字母、下画线(_)或美元符号($)。
  • 余下的字符可以是下画线、美元符号或者任何字母或数字字符。

下面这些变量名都是合法的:

var test
var objectName
var —phone
var $1

为了代码的可读性,在命名变量时还应该遵循一定的命名风格。因为 Qt 是基于 C++ 的应用框架,QML 又是 Qt 框架的一部分,这里建议和 Qt C++ 代码采取同样的命名风格—驼峰命名法。

对于变量(包括函数名),以小写字母开始,单词之间采用驼峰命名法。对于类名,以大写字母开始,单词之间采用驼峰命名法。

三、原始类型

ECMAScript 有 5 种原始类型,即 Undefined、Null、Boolean、Number 和 String。每种原始类型定义了它包含的值的范围及其字面量表示形式。

ECMAScript 提供了 typeof 运算符来判断一个值的类型,如果这个值是原始类型,typeof 还会返回它具体的类型名字;而如果这个值是引用值,那么 typeof 统一返回 ”object” 作为类型名字。示例如下:

import QtQuick 2.2

Rectangle {
	Component.onCompleted:{
		var name = "Zhang San Feng"
        console.log(typeof name) // 输出:qml:string
        console.log(typeof 60) // 输出:qml:number
	}
}

变量 name 的类型是 string,字面量 60 的类型是 number。其中 “qml:” 是使用 console.log 输出信息时携带的前缀。

1. Undefined 类型

Undefined 类型只有一个值,即 undefined。当声明的变量未初始化时,该变量的默认值就是 undefined。例如:

var temp

上面的代码声明了变量 temp 但并未显式地讲行初始化,它的值将被设置为 undefined, 这和 C++ 不同。ECMAScript 的这一特性:未初始化的变量也有固定的初始值,我们可以将一个变量和 undefined 比较来实现一些业务逻辑。比如:

var runOnce;
...
if(runOnce == undefined) {
    runOnce = true
}
else {
    ...
}

当函数没有明确的返回值时,返回的值也是 undefined,如下所示:

function blankFunc(){}
console.log(blankFunc() == undefined) // 输出:true

2. Null 类型

Null 类型也只有一个值,即 null。

你可以显式地将一个变量初始化为 null,然后据此实现一些逻辑。

3. Boolean 类型

Boolean 是 ECMAScript 中最常用的类型之一,它有 true 和 false 两个值。

4. Number 类型

Number 类型是最特殊的,它既可以表示 32 位的整数,也可以表示 64 位的浮点数。你在 QML 代码中直接输入的任何数字都被看作是 Number 类型的字面量。

下面的代码声明了存放整数值的变量:

var integer = 10

数字类型的最大值是 Number.MAX_VALUE,最小值是 Number.MlN_VALUE,它们定义了 Number 值的外边界,所有的 ECMAScript 数都必须在这两个值之间。

5. String 类型

ECMAScript 中的 String 类型是作为原始类型存在的,它存储 Unicode 字符,对应的 Qt C++ 类型为 QString。当你混合 C++ 和 QML 编程时,所有的 QString 类型的变量都会被映射为 ECMAScript 中的 String。

字符串字面量可以用双引号(")或单引号(')来声明。而在 Qt 中,只能用双引号, 单引号表示字符。为了一致性,建议你尽可能不要使用单引号表示字符串。在 ECMAScript 中没有字符类型,这也是为什么你可以使用单引号来表示字符串的原因。下面的两行代码都是有效的:

var name = 'Lv Bu'
var name = "Guan Yu"

四、类型转换

如果一种编程语言不支持类型转换,那真是无法想象。在 ECMAScript 中,类型转换非常简单。

1. 转换成字符串

Boolean、Number、String 三种原始类型,都有 toString() 方法,可以把它们的值转换为字符串。比如下面的代码在 Qt 中可以正常运行:

var name = "Zhang San Feng"
console.log(name.toString())
console.log(true.toString())
var visible = false
console.log(visible.toString())
var integer = 3.14159
console.log(integer.toString())

Number 类型的 toString() 方法还可以按基转换,比如:

var integer = 13
console.log (integer.toString(16)) // 输出: D

如果你不指定数基,那不管原来是用什么形式声明的 Number 类型,toString() 都按十进制输出。

2. 转换成数字

parselnt() 和 parseFloat() 可以把非数字的原始值转换成数字,前者把值转换为整数,后者把值转换成浮点数。这两个方法只能用于 String 类型,如果你对其他类型调用它们, 返回值将是奇葩的 NaN。

parselnt() 和 parseFloat() 会扫描字符串,直到遇到第一个非数字字符时停止,将转换的结果返回。比如parselnt(”2014年")将会返回 2014。对于 parseFloat(),会将第一个小数点作为有效字符,而 parselnt() 则不会。

下面是一些示例:

var numl = parselnt ("2014 年") // 输出:2014
var num2 = parselnt ("OxC") // 输出:12
var num3 = parselnt ("3.14") // 输出:3
var num4 = parselnt ("green") // 输出:NaN_
var num5 = parseFloat ("3.14159") // 输出:3.14159
var num7 = parseFloat ("Am I Float") // 输出:NaN

parselnt() 还支持基模式,下面是一些示例:

var numl = parselnt ("AK47", 16) // 输出:10
var num2 = parselnt ("AK47", 10) // 输出:NaN
var num3 = parselnt ("010", 8) // 输出:8
var nun4 = parselnt ("010", 10) // 输出:10

需要注意的是,代表浮点数的字符串必须以十进制形式表示,比如parseFloat(“OxFE”),返回 NaN。

3. 强制类型转换

如果你是 C/C++ 程序员,对强制类型转换一定又爱又恨。ECMAScript 也支持强制类型 转换,有三种转换:

  • Boolean(value),把 value 转换成 Boolean 类型。
  • Number(value),把value转换为数字(整数或浮点数)。
  • String(value),把value转换成字符串。

五、函数

ECMAScript 中的函数,就是具名的、可重复使用的代码块。另外,ECMAScript 不支持函数重载。

1. 函数语法

函数语法如下:

function functionName(arg1, arg2, ..., argN){
	// 要执行的代码
}

function 是定义函数时必须使用的关键字。functionName可以任意取,符合变量命名规则即可。 arg1 到 argN 是函数的参数,当然也可以没有参数。花括号内是要执行的代码块。

无参函数示例:

function quitApp(){
	Qt .quit ();
}

带参函数示例:

function showError(msg){
	console.log("error - ", msg);
}

function travel(country, city){
	console.log("Welcome to ", city, " , ", country);
}

当我们使用函数参数的时候,参数就像不带 var 运算符的变量声明一样。这与 C++ 中必须给函数参数指明类型大相径庭。

2. 函数的返回值

ECMAScript 中的函数,默认都是有返回值的,即便你没有显式使用 return 语句,它也会返回 undefined。如果你想把函数运算的结果返回给调用它的地方,可以使用 return 语句。下面是个简单的示例:

function add(numberl, number2){
	var result = number1 + number2;
	console.log(number1, "+" ,number2, result);
	return result;
}

你可以这样调用 add() 函数:var ret = add(100, 34);。

六、运算符

ECMAScript 的运算符和 C++、Java 等语言的差不多,具体内容不再赘述。这里只重点介绍一下关键字运算符。void、typeof、instanceof、new、delete 这些都是关键字运算符。

  • void 运算符比较特殊,它放在一个表达式前,舍弃表达式的值,返回 undefined。
  • typeof 前面讲过了,对于原始值,返回原始类型;对于引用值,返回 object。这导致你无法准确判断一个对象的引用类型,所以 ECMAScript 引入了 instanceof 运算符。
  • instanceof 用来测试一个对象的实际类型,你需要显式指定要测试的类型。例如:
  • var str = new String ("hello world"); console.log (str instanceof String); // 输出:true
  • new 运算符用来创建一个对象,前面用了很多次了,不再赘述。 delete 运算符比较特别,在 QML 中,一般它只能删除一个对象内由你定义的属性,而框架定义的那些核心属性,多数是你不能删除的。我们在 ECMAScript 中调用 delete,多数时候是解除对对象的引用,以免老有人引用某个对象而导致它逍遥法外。

七、使用 console

console 提供了输出日志信息、断言、计时器、计数器、性能分析等功能,这里只介绍前三个我们经常用到的功能。

1. 输出日志信息

console对象提供了多个打印调试信息的方法:

  • console.log();
  • console.debug();
  • console.info();console.warn();
  • console.error();

2. 断言

console.assert() 提供断言功能,它接受一个表达式,当表达式的值为 false 时会输出调试信息,打印 QML 所在行。例如:console.assert (false)。

如果你传递了额外的参数给 console.assert(),它会在控制台输出这些信息。示例:

var years = 0;

for (; years < 18; years++){
	console.log("I\'m minor"); 
    continue;
	console.log ("You shoult not see me"};
}

console.assert(years < 18, years);

上面的断言语句,将会输出下列信息:

18
onCompleted (file:///F:/projects/qtquick/qmls/show_type.qml:187)

需要注意的是,在 QML 中,使用 console.assert(),断言失败,程序并不会终止运行。

3. 计时器

console 提供了计时器功能,方便我们测量某些代码的耗时情况。

console.time(tag) 启动定时器,字符串类型的 tag 是必需的。console.timeEnd(tag) 停止计时器,在控制台输出某个标签对应的耗时信息。tag 是必需的。 下面是简单的示例:

console.time("regexp");

var str = "We are dogs;\nYour dogs;\nWe want meat.\nPlease.";
var lines = str.match(/^We.*/mg);
console.log(lines.length);
console.log(lines);
console.timeEnd("regexp");

// 输出:regexp: 7ms

文章转自博客园(fengMisaka):【QML 快速入门】QML语法-基础篇

本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓

猜你喜欢

转载自blog.csdn.net/QtCompany/article/details/131904108