当初接触Qt时,还是Qt4时代,最先学的是QML和Qt Quick,对Qt的C++部分一窍不通。虽说最先学的是QML和Qt Quick,但也不过是学了些皮毛,后来一直专注于Qt的C++开发,最开始学的就几乎忘光了。进入Qt5时代以后,QML和Qt Quick都有了长足的进步,最近心血来潮,决定好好学学这一方面的技术,毕竟最先让我爱上Qt的是QML和Qt Quick,而且这方面的不足总让我觉得在Qt这方面缺了一块“拼图”(这是一个可以逼疯XX座的问题)。现在就来补上这块“拼图”吧!下面把学过的要点记录下,以防健忘的我学完就不知道还给谁了。
qmlscene
qmlscene工具可以用来加载qml文件,在测试和调试代码时非常有用。使用时只需在cmd中输入如下命令:
qmlscene --help
qmlscene <path>
......
QML和Qt Quick
QML(Qt Meta-Object Language),实现并扩展了ECMAScript,是一种语法格式类似于CSS的标记性语言,用于描述用户界面;
Qt Quick模块是开发QML应用程序的标准库,提供使用QML构建用户界面所需的一切;
QML和Qt Quick的关系类似于C++和STL的关系
Qt Quick Application和Qt Quick Controls Application的区别
建立Qt Quick项目时有两种项目类型,经过实际对比,建立项目后的模板区别如下:
(1) Qt Quick Controls Application
建立项目时有选项Enable native styling可供勾选;
若勾选了Enable native styling,pro文件内声明使用widgets模块,因为勾选功能依赖于widgets。相对应的,C++代码中的main函数使用widgets模块中的QApplication(继承自QGuiApplication,gui模块);
若没有勾选Enable native styling,pro文件内没有使用widgets模块的声明,因为Qt Quick Controls里的控件实现本身并不依赖widgets模块。相应的,C++代码中的main函数只能使用gui模块(无显式声明下默认加载)中QGuiApplication;
生成的main.qml文件中,主窗口使用的是QtQuick.Controls下的ApplicationWindow(继承自Window,QtQuick.Window下),如果不使用Enable native styling选项,Qt Quick Conrols Application和Qt Quick Application模板项目的区别几乎仅限于此;
(2) Qt Quick Application
pro文件中没有使用widgets模块的声明,相对应C++代码中的main函数使用QGuiApplication,而不是widgets模块下的QApplication;
生成的main.qml文件中,主窗口使用的是QtQuick.Window下的Window,而不是QtQuick.Controls下的ApplicationWindow
QML对象id
QML的对象id在一个qml文件内必须唯一,且只能小写字母或下划线开头
翻译文本
相对于C++中常用的tr()函数,qml中使用qsTr()
QML中的附加属性
QML中的附加属性有点类似于C#中的附加属性,让我想起了WPF中像DockPanel.SetDock()这样的函数,当然qml中用起来要简单和强大得多
控件Style中的control属性
control属性指向控件的实例,可以很方便的获取所属控件的一些属性,从而对样式做出动态调整,不过编辑器并没有智能提示,呵呵......
ECMAScript
Qt文档中有相关的描述;
ECMAScript仅仅是一个描述,并不是具体实现了的语言(如JavaScript,QML),QML是针对Qt的ECMAScript的扩展实现;
ECMAScrip是弱类型的,变量定义只需var即可;
ECMAScrip的语句末分号可有可无;
代码注释格式和C++是一样的(//,/**/);
和Java、C#类似有垃圾收集机制;
所有函数都有返回值(默认undefined),函数声明都用function关键字开头,不需要声明返回值类型和参数类型(你看看var干啥用的就知道为什么了);
String类型不同于Qt里的QString,类似于C#中的string类,初始化之后都是只读的,处理string类后往往都是返回保存结果的新实例,原来的实例原封不动;
类(对象定义)的实例创建可以是new,也可以用字面量的形式创建,两种形式都可以动态添加属性和方法。不过有趣的是,如果通过字面量的形式创建实例,枚举属性的时候,创建时就具有的“先天”属性都是自动排好序的,而创建后添加属性则按添加顺序排在“先天”属性的后面;
console对象很强大,输出调试信息、断言、计时器、计数器、性能分析等等一应俱全哦;
ECMAScript定义了三个内置对象:Global、Math和JSON。三个内置对象提供了很多基础对象的构造函数和很多有用的工具方法;
Component
只有在定义内嵌组件时,才需要用Component对象包含组件内容,在独立文件定义组件时不需要Component对象;
Component除了定义id和包含一个根Item之外,不能包含其他内容;
定义组件时顶层Item的id与组件实例的id是相互独立的;
在独立文件中定义的组件,使用方式和Qt Quick中的标准组件完全一致;
Layout中的Image
Qt Quick核心编程里,在讲到TabView和TabViewStyle时,给出了一段示例代码,一字不差地敲了一遍运行,结果发现运行结果和书中不一样。经过研究发现Image放到各种Layout中时的width和height属性不起作用,只有使用Layout.preferredWidth和Layout.preferredHeight附加属性才能解决问题,难道这是我使用的Qt版本的Bug?
动画
Animation类的started、stopped信号只有单独的顶层动画对象才会触发,如果动画在在动画分组中、Behavior中或者在Transition中,这两信号都不会触发
按键处理Keys
通过附加属性Keys可以响应按键,其中Keys最为普通的两个按键pressed和released信号,类似于Qt C++中的keyPressEvent和keyReleaseEvent,这两个信号带有一个类型为KeyEvent,名称为event的参数。和Qt C++中类似,处理掉的按键应甚至event的accepted属性为true,以免继续传递。
另外,附加了Keys属性后,还需要设置对应元素的focus属性为true才能接收按键消息哦。