×
Namespaces

Variants
Actions

Qt Quick Components 页面管理

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

代码示例
文章
zhouhl 在 24 Jul 2011 创建
最后由 renlin 在 12 Jul 2012 编辑

Contents

概述

在开发程序的时候,通常我们都不止有一个界面,并且希望程序能在这些界面之间自由切换。页面少的话还好处理,如果页面很多的话就迫切需要一种很好的页面管理机制。
Qt Quick Components 为开发者构建UI提供了一系列的 QML components。其中非常重要的两个就是 QML Page Element 和 QML PageStack Element,它们的出现为开发者提供了一套页面管理的系统。本文就为大家介绍一下它们的用法,阐述一下其底层实现机制,并分享一下使用中需要注意的问题,最后为大家提供一个页面切换的例子程序。

使用item page还是component page?

PageStack顾名思义就是一个存放页面的栈结构。位于栈顶的就是当前活动的显示在界面中的页面。我们可以直接像下面这样在QML文件中定义一个页面:

Page{
id: myPage

}

这样定义的页面叫做item page。 于是我们就可以把这个页面放到栈上让它显示出来了:

pageStack.push(myPage)

这样我们是把一个“对象”push到了栈上。并且当这个“对象”在栈上的时候它的parent就变成这个栈了,当这个对象被pop出栈之后,它的parent才恢复为原来的。栈并不复制或销毁这个page 对象,它只是拥有这个对象一会儿。因此你的程序总是可以访问到这个对象,但是这个对象一直是需要占用内存的。

item page虽然可以实时访问,但它总是一直占用着内存,那么如果我们的程序中需要用到大量的页面,显然使用item page是不合适的。那么此时我们就可以使用 component page。


使用 component page 有两种方式:

  • 第一种方式,我们可以通过 Qt.resolvedUrl 直接给 PageStack::push ( page, properties, immediate ) 传递一个字符串。例如:
pageStack.push(Qt.resolvedUrl("FilePage.qml"));

这样做实际上是把一个 url 字符串 push 到栈上,这个 url 对应一个 component 文件的 url。于是栈会调用 Qt.createComponent 来创建这个 component,并把这个 component 的一个实例放到栈上。当我们 pop 出这个实例的时候,栈就会自动把它销毁。

  • 第二种方式,通过 Qt.createComponent 给 PageStack::push ( page, properties, immediate )传递一个 Component。例如:
var component = Qt.createComponent(componentFileName) 
if (component.status == Component.Ready)
pageStack.push(component);

这样做的话,栈会首先创建这个 component 的一个实例,然后把这个实例对象放到栈上。当你把这个 page 对象从栈上 pop 出来的时候,栈就把这个 page 对象给销毁了,你就再也无法访问到它了。也就是说你只能访问到当前在栈上的页面中的内容。如果你想让 pop 出去的页面中存放写持久数据的话,那就需要自己把数据存到一个例如 model 的东西里面。

这种 component 类型的页面对于那些有许多页面的程序来说是非常有用的。因为它可以有效的使用内存。只有那些当前在栈上的页面才占用内存,当页面从栈中弹出的时候,它们就被自动销毁了,它们所占用的内存就被自动释放了。

使用使用Qt.createComponent 需要注意的问题

QML 遵循 Qt 标准的父子销毁规则,也就是 parent item 被销毁了那么 child item 也自动被销毁。 在把创建的 Component 压栈之后,Component 归栈所有,在 pop 之后 Component 会被销毁,并且这个 Component 的孩子也会被销毁。

当你使用 Qt.createComponent() 的时候,创建出的 Component 的父亲是调用 Qt.createComponent() 的那个item。

如果在 A.qml 中,有这样一句:

pageStack.replace(Qt.createComponent("B.qml")),

由于 B 这个 Component 是在 A.qml 中创建的,因此 B 的 parent 是 A。但是replace 的意思是销毁当前栈顶的页面并把新创建的页面放到栈顶。也就是先销毁 A, 然后把 B 放到栈顶, 但是这时候由于 B 的parent A 被销毁了,因此 B 也被销毁了,下面要做的是把已经销毁的对象放到栈顶,当然会出错的。

有这样几个办法可以避免这个错误,其一,使用Qt.resolvedUrl("MyPage.qml")。这样的话 MyPage 的 parent 就是栈了,我们就不必关心删除什么东西会有什么意外影响了。
其二,如果必须要使用 Qt.createComponent 的话,就把新创建的页面的 parent 手动设置成一个不会被销毁的对象。例如:

var myPage = Qt.createComponent("MyPage.qml") 
myPage.parent = pageStack.parent
pageStack.replace(myPage)

下载例程

Media:QmlPageNavigation.zip

相关链接

This page was last modified on 12 July 2012, at 04:53.
170 page views in the last 30 days.