qml入门学习笔记(2)

创建菜单页

上节中阐述了如何创建元素并在单独的QML文件中设置行为.本节将说明如何导入QML元素,如何重用已有组件构建其他组件.

菜单显示一列内容,其中的每个项都可以执行一个动作.在QML中,有很多种方式创建菜单.首先,我们创建包含可执行不同动作按钮的菜单.菜单代码在FileMenu.qml中.

import QtQuick 1.0 \import the main Qt QML module

import “folderName” \import the contents of the folder

import “script.js” as Script \import a Javascript file and name it as Script

上述语法展示如何使用import关键字.这里需要使用不在同一目录中的JavaScript文件或QML文件.由于Button.qml与FileMenu.qml在同一目录中,不必导入Button.qml就可直接使用.可直接使用Button{}声明一个按钮元素,与Rectangle{}的声明一样.

FileMenu.qml:

 Row{

     anchors.centerIn: parent

     spacing: parent.width/6



     Button{

         id: loadButton

         buttonColor: "lightgrey"

         label: "Load"

     }

     Button{

         buttonColor: "grey"

         id: saveButton

         label: "Save"

     }

     Button{

         id: exitButton

         label: "Exit"

         buttonColor: "darkgrey"



         onButtonClick: Qt.quit()

     }

 }

在FileMenu.qml中,声明了三个按钮元素.他们都在一个Row元素中声明的,这是一个定位器,将其子元素按行定位.Button声明在Button.qml中,与上节定义的Button.qml一致.新创建的按钮可设置属性绑定,在exitButton上增加了onButtonClick处理函数,由Button.qml中定义的onButtonClick来触发调用.

Row定义在Rectangle中,创建了包含一行按钮的矩形容器.这个额外的矩形采用间接的方式在菜单中组织了一行按钮.

这个阶段定义的编辑菜单非常简单.菜单按钮具有的标签为:Copy,Paste,Select All.

结合前面介绍的知识和定义的组件,我们已经可以组合这些菜单页生成一个菜单栏了,包括选择菜单的按钮,下面看看如何在QML中组织这些数据.

实现菜单栏

我们的文本编辑器程序需要使用菜单栏显示菜单.菜单栏可以切换不同的菜单,用户可选择显示哪个菜单.菜单间的切换比仅仅显示在一行中需要更多组织信息.QML使用模型和视图来组织数据和显示数据.

使用数据模型和视图

QML有用来显示数据模型(data models)的不同的数据视图(data views ).我们的菜单栏将显示列表中的菜单,头部显示一行菜单名称.菜单列表定义在VisualItemModel中.VisualItemModel元素中包含需要显示的元素,如Rectangle元素和导入的UI元素.其他模型类型如 ListModel 元素则需要显示其数据的代理(视图).

我们在menuListModel中定义两个可视化项,一个FileMenu一个EditMenu.并自定义这两个菜单,显示在ListView中.MenuBar.qml文件包含了简单的QML定义,编辑菜单定义在EditMenu.qml中.

 VisualItemModel{

     id: menuListModel

     FileMenu{

         width: menuListView.width

         height: menuBar.height

         color: fileColor

     }

     EditMenu{

         color: editColor

         width:  menuListView.width

         height: menuBar.height

     }

 }

ListView元素用来显示其代理模型.代理声明可在Row元素中显示模型元素,也可在Grid中显示模型元素.menuListModel已经定义需要显示的项了,因此,我们不再需要声明模型了.

 ListView{

     id: menuListView



     //Anchors are set to react to window anchors

     anchors.fill:parent

     anchors.bottom: parent.bottom

     width:parent.width

     height: parent.height



     //the model contains the data

     [b]model: menuListModel[/b]



     //控制菜单开关的移动

     snapMode: ListView.SnapOneItem

     orientation: ListView.Horizontal

     boundsBehavior: Flickable.StopAtBounds

     flickDeceleration: 5000

     highlightFollowsCurrentItem: true

     highlightMoveDuration:240

     highlightRangeMode: ListView.StrictlyEnforceRange

 }

另外,ListView从Flickable继承,使列表可响应鼠标拖拽和手势.上述代码的最后部分设置flick属性可在视图中创建出期望的flick移动效果.特别是highlightMoveDuration属性设置flick的延续时间.较高的highlightMoveDuration值使菜单切换变慢.

ListView通过索引维护模型项目,模型中的可视项都是通过索引进行访问的,索引顺序与声明顺序相同.修改当前索引值会改变ListView中的高亮项.菜单栏的头部分证实了这个效果.这里一行中有两个按钮,点击后会改变当前菜单.点击fileButton将当前菜单切换为file菜单,由于FileMenu在menuListModel中第一个声明,因此其索引为0.同样,点击editButton将当前菜单切换为EditMenu.

labelList矩形的z属性值为1,强调其显示在菜单栏的最前面.项的z属性值越高越靠前显示.z属性值默认为0.

 Rectangle{

     id: labelList

     ...

     z: 1

     Row{

         anchors.centerIn: parent

         spacing:40

         Button{

             label: "File"

             id: fileButton

             ...

             onButtonClick: menuListView.currentIndex = 0

         }

         Button{

             id: editButton

             label: "Edit"

             ...

             onButtonClick:    menuListView.currentIndex = 1

         }

     }

 }

菜单栏可以通过flick操作或点击上面的菜单名称按钮.切换菜单效果很直观生动.