现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

三天学会QML

2014-07-01 05:47 工业·编程 ⁄ 共 5957字 ⁄ 字号 暂无评论

    目标: 能够熟练掌握QML的开发。

    第一天

    QML是什么?

    官方有很标准的定义,我个人觉得它是一个脚本语言,能够通过该脚本语言创建动态的场景,有点类似于FLASH。

    为什么要学习QML?

    因为现代程序对界面的需求越来越高,而一般的C++界面设计比较复杂,所以需要一种能够快速建立界面,并且能够很好的与下层逻辑进行衔接的方案,QML就满足了这样的需求。

    QML初步理解:

    看了QML的一些示例代码,感觉QML是一种脚本语言,用于动态创建一个场景。也许大家觉得“QML是一种脚本语言,用于动态创建一个场景”这句话就和废话差不多,但其实却差很多。它是一种脚本语言,那就说明它有它的格式,所以大家在看代码的时候,可以理解它就是这样,先不要问为什么这样;它用于动态创建一个场景,这个非常重要,一般的程序很少有感觉是场景的,但写QML的过程你会非常直观的感觉是在创建一个场景,安排各种各样的事物,让它们具有不同的属性特征,然后某些物体属性的变化,或用户的交互,引发另外一个物体的变化。

    学习QML的过程,就是学习如何成为一名初级导演的过程。

    下边有几个问题首先需要解决。

    1、 我们如何来创建一个物体?以及可以创建哪些物体?

    2、 一个物体的变化,或用户的交互,如何引发场景的变化?

    QML内部定义了很多的对象类型,我们可以直接创建这些对象类型的物体,至于有哪些对象类型,暂时先不叙述,因为以后我们会一个一个逐渐学习到。创建一个物体的过程就更加简单了,按照QML的语法规则,写几行文字就可以创建一个物体了,其实本质上就是写了一句,给我创建一个拿刀的身高180CM的男性士兵,这么简单。

    现在让我们来看看,如果我想创建一个简单的场景,里边包含一个显示文字信息的物体,并且让它出场时就显示“我是一头猪”,该怎么操作?首先先创建一个场景,基本代码如下:

    Rectangle

    {

    // 既然是场景,那肯定要设定个大小

    width:500 // 场景的宽

    height:500 // 场景的高

    // 场景内包含的物体信息

    // 显示文字信息的物体

    Text

    {

    x:100

    y:100

    text:"I'm a pig" // 为啥是英文?因为刚刚测试中文显示有点问题,BUG?

    }

    }

    以下是运行的结果:

    上边的代码,虽然很简单,但里边包含了太多的东西,需要一点点进行剖析,这样大家才能够更加扎实的逐步深入掌握精华。

    1、 脚本,或者场景剧本的书写格式是什么样的?

    大家可以很直观的感觉到,是一种直观的物体包含物体的组织方式,类似于树,从根逐渐发展到叶子。而这里的最根节点,我们可以认为就是场景。

    格式基本如下:

    物体

    {

    属性:属性值

    物体

    {

    ….

    }

    }

    2、 什么是物体的属性?

    就像自然界的东西,每个物体都有自己的属性特征,例如美女,就有身高,体重,三维等等很重要的几个属性信息,如刚刚示例中场景有大小这样的属性,文字有内容属性,有位置属性等。

    3、 怎么能够知道哪些物体有哪些属性?属性叫什么名字?

    这个问题真的有点难度了,这个可真是基本功了。不过不要紧,咱可以学点精髓,然后用啥看啥,看啥会用啥就可以了。那啥叫精髓?就是能看懂QML基本文档信息,就叫精髓了。例如上边示例中的Text那个东西的参考文档,http://doc.qt.nokia.com/4.7/qml-text-members.html

    这个文档中有Text这类物体的所有属性信息,太多了,很难记住,随便选一个先看看,例如font.pointSize这个属性,看上去像是设置文字字体大小的,打开链接看到该属性的描述信息,首先,该属性的取值是一个数字,其次,它确实是用来设置字体大小的,那么,我们就来看看将刚刚示例中的字体大小改为30看看,修改后代码如下:

    Rectangle

    {

    // 既然是场景,那肯定要设定个大小

    width:500 // 场景的宽

    height:500 // 场景的高

    // 场景内包含的物体信息

    // 显示文字信息的物体

    Text

    {

    x:100

    y:100

    // 新增加属性,设置字体大小

    font.pointSize:30

    text:"I'm a pig" // 为啥是英文?因为刚刚测试中文显示有点问题,BUG?

    }

    }

    运行结果如下:

    哈哈,明显比刚刚大了,说明这很有效果。

    4、 还能创建哪些物体?

    和刚刚一样,给大家一个链接,上边是最基本的显示相关的物体,大家可以瞅瞅看看。http://doc.qt.nokia.com/4.7/qml-basic-visual-elements.html

    大家可以看到QML Text Element这行,就是刚刚显示文字的那个物体,点击链接进入后就可以看到这个物体相关的属性信息了,我们这里可以举个新的示例,比如,Image物体,从名称上来看,我们可以猜想这应该是和图片相关的一个物体,打开链接后,看到该物体有一个source的属性,看属性描述应该是描述图片的链接信息,这样我们就现在场景中打开一个小图片,代码如下:

    Rectangle

    {

    // 既然是场景,那肯定要设定个大小

    width:500 // 场景的宽

    height:500 // 场景的高

    // 场景内包含的物体信息

    // 显示文字信息的物体

    Text

    {

    x:100

    y:100

    // 新增加属性,设置字体大小

    font.pointSize:30

    text:"I'm a pig" // 为啥是英文?因为刚刚测试中文显示有点问题,BUG?

    }

    // 显示图片物体

    Image

    {

    source:"qtlogo.png"

    }

    }

    我们现在已经学习了如何创建对象,如何设置对象属性,应该是一个很伟大的目标完成了。

    大家看到这里应该可以随意创建一个静态的场景了吧?好好玩一玩吧,玩的多了,下一步的学习将更加有效果。

    第二天

    昨天对QML已经有了一个非常大的了解,可以随意创建一个静态的场景了,虽然可以小兴奋一下了,但我们还是应该牢记,革命尚未成功,同志仍需努力。

    既然我们说QML是用来描述场景的,那么场景中的物体就会进行交互,从本质上来说,QML将场景内的对象分为三个大的类别,基础物件类,例如文字,图像等,用户交互类,动作执行类。

    接下来需要攻克的一个难点就是,如何与场景进行交互?

    按照上边分的类别,学习场景进行交互的过程,其实就是学习用户交互对象的过程。但我们还是仅仅会学习“精髓”部分,因为这样大家才可以自己无限的扩展。其实本质上,大家有了前一篇文章的学习过程,应该即时不用看这篇文章也会学习的很不错的。

    我比较喜欢需求驱动式的学习方法,这样对大家以后自己用也更加有实战意义。那现在我们来假想一个需求,上篇文章中我们创建了一个有图片,有文字的场景,现在让我们加入点交互,先简单点,鼠标点击图片,文字颜射变为红色。

    如和添加鼠标点击交互呢?先来看看交互都有哪些对象可以用。

    http://doc.qt.nokia.com/4.7/qml-basic-interaction-elements.html

    从名字上来看,应该是MouseArea这个对象靠谱。打开对象描述,里边的属性大家可以自己熟悉了解,我会在后来的文章中提及一些比较重要的属性,在属性下边,是该对象的触发信号描述,这个非常重要,用户的交互就是发生了一个触发,我们需要如何交互,本质上就是对触发进行如何处理的过程。

    先把上边任务的代码放上来

    Rectangle

    {

    // 既然是场景,那肯定要设定个大小

    width:500 // 场景的宽

    height:500 // 场景的高

    // 场景内包含的物体信息

    // 显示文字信息的物体

    Text

    {

    // 给这个对象起个名字

    // 这样方便在其它地方修改这个对象属性信息

    // 现在主要是方便鼠标点击后的处理

    id:text

    x:100

    y:100

    // 新增加属性,设置字体大小

    font.pointSize:30

    text:"I'm a pig" // 为啥是英文?因为刚刚测试中文显示有点问题,BUG?

    }

    // 显示图片物体

    Image

    {

    id:image

    source:"qtlogo.png"

    }

    // 鼠标处理添加

    MouseArea

    {

    // 定义鼠标点击的范围

    // 总得定义点哪里吧?

    anchors.fill: image

    // 点击后的处理

    // 将文字对象的颜色改为红色

    onClicked:{ text.color="red"}

    }

    }

    这个结果图片不好抓,大家就自己来跑跑测试看吧。

    既然都这样了,不如我们来个更加好玩一点的,让鼠标滑到图片上时,图片变大,移出时变小。

    Rectangle

    {

    // 既然是场景,那肯定要设定个大小

    width:500 // 场景的宽

    height:500 // 场景的高

    // 场景内包含的物体信息

    // 显示文字信息的物体

    Text

    {

    // 给这个对象起个名字

    // 这样方便在其它地方修改这个对象属性信息

    // 现在主要是方便鼠标点击后的处理

    id:text

    x:100

    y:100

    // 新增加属性,设置字体大小

    font.pointSize:30

    text:"I'm a pig" // 为啥是英文?因为刚刚测试中文显示有点问题,BUG?

    }

    // 显示图片物体

    Image

    {

    id:image

    source:"qtlogo.png"

    }

    // 鼠标处理添加

    MouseArea

    {

    // 定义鼠标点击的范围

    // 总得定义点哪里吧?

    anchors.fill: image

    // 点击后的处理

    // 将文字对象的颜色改为红色

    onClicked:{ text.color="red"}

    // 需要先启动捕捉这个动作,默认不启动

    // 默认不启动的原因,应该是这个动作可能会耗费不少的计算机资源

    hoverEnabled:true

    // 当鼠标进入图片领域,则放大图片1.5倍

    onEntered:{image.width=image.width*1.5; image.height=image.height*1.5}

    // 当鼠标离开图片领域,则恢复图片大小

    onExited:{ image.width=image.width/1.5; image.height=image.height/1.5}

    }

    }

    今天就先到这里吧,其它几个交互对象,大家可以先自己测试看看,相信自己测试以后更有发言权。

    第三天

    当你能够随意创建一个对象,随意添加一个交互动作时,你是不是觉得自己已经很NX了?如果这样,那只能说我们的视界还是有点小。

    如果能够深入考虑一下问题,就会问自己几个问题,QML真正的优势到底在哪里?和FLASH有和异同?创建大程序时如何管理数据对象?这些问题先留给大家思考吧,因为我也还在思索着,哈哈。

    今天就先来再做一个简单一点的例子,在页面上放两个文本对象,当编辑其中一个时,另一个对象的文本信息发生同样的变化。

    开发思路:放置两个文本对象这个非常简单,但如何能够让一个对象的变化引发另一个对象的变化呢?回想到昨天鼠标操作对象有一个触发器属性,也许文本对象也有一个触发器对象属性可以用,我们先看看。http://doc.qt.nokia.com/4.7/qml-textedit.html

    看了以后发现没有,不过在它的一个例子中发现了一句话onCursorRectangleChanged,是不是觉得有点感觉奇怪,这个是从哪里来的?怎么没见说明的地方,其实啊,它是QML默认的一个规则(猜的),可以通过类似这种on属性Changed的形式来捕捉属性的修改信息,既然如何,那么应该一个文本对象的修改,引发另一个文本对象的修改问题不大了。

    代码:

    Rectangle

    {

    width:500 // 场景的宽

    height:500 // 场景的高

    // 其中一个文本对象

    TextEdit

    {

    id:text1

    width: 240

    text: "Text Edit"

    font.family: "Helvetica"

    font.pointSize: 20

    color: "blue"

    onTextChanged:{text2.text=text}

    }

    // 其中一个文本对象

    TextEdit

    {

    id:text2

    y:200

    width: 240

    text: "Text Edit"

    font.family: "Helvetica"

    font.pointSize: 20

    color: "red"

    onTextChanged:{text1.text=text}

    }

    }

    从抓图上来看还不错吧,哈哈,我自己感觉也还不错。

    咱们再来玩一个有意思的例子。这次我们做一个很简单的图片浏览器,鼠标拖动,然后换一张图片,这个和现在很多手机上的看图片方式一致。

    开发思路:首先需要解决一个问题,图片加载,前边我们至少用过一个图片对象,它具备了加载图片的功能,虽然还不知道动态加载是否存在问题,但至少静态加载没啥大问题,所以图片加载应该不是问题。其次,如何实现图片的拖动效果?这个确实很棘手,第一个想到的方法就是捕捉鼠标的移动,然后对此进行处理,从而移动图片对象,达到拖动效果,不过这个方案感觉还挺复杂,先当做备选方案吧,现在在看看QML有没有提供更简单的方法。

    刚刚打开QML文档找了半天,终于被我找到一个好东西,ListView,它能够将多个条目信息组织成一个列表,而这个列表提供了一个类似的方法,snapMode,现在可以先测试看看这个方法灵不灵。

    代码:

    // 场景

    Rectangle

    {

    width: 500;

    height: 500

    // 图片条目数据组织

    VisualItemModel {

    id: itemModel

    Image {

    width: view.width; height: view.height

    source:"1.jpg"

    }

    Image {

    width: view.width; height: view.height

    source:"2.jpg"

    }

    Image {

    width: view.width; height: view.height

    source:"3.jpg"

    }

    Image {

    width: view.width; height: view.height

    source:"4.jpg"

    }

    }

    ListView {

    id: view

    anchors { fill: parent }

    model: itemModel

    preferredHighlightBegin: 0; preferredHighlightEnd: 0

    highlightRangeMode: ListView.StrictlyEnforceRange

    orientation: ListView.Horizontal

    snapMode: ListView.SnapOneItem; flickDeceleration: 2000

    }

    }

    经过我测试,和我们预期要完成的功能一致,完了以后,真想说,Fuck,shit,So easy!

    电脑中临时没有图片,所以临时把我儿子搬出来亮亮,哈哈。看着他照片,写代码更有激情了。从这个例子我们学到一个非常重要的东西,一件事情可能有很多种完成的方案,但我们一定要在动手之前尽量多多收集一下相关信息,否则,很可能花了时间,老板还不买账。

    今天先到这里吧,两个例子也不少了,再多我也想不出来了。

    给我留言

    留言无头像?