Qt Reference Documentation

QML PageStack Element

Defines a container for pages and a stack-based navigation model. More...

Inherits Item

  • List of all members, including inherited members
  • Properties

    Methods

    Detailed Description

    The PageStack component provides a stack-based navigation model that you can use in your application. A stack-based navigation model means that a page of content for your application is pushed onto a stack when the user navigates deeper into the application page hierarchy. The user can then go back to the previous page (or several pages back) by popping a page (or several pages) off the top of the stack.

    See the Page Based Application Navigation overview for a higher level discussion about pages and page stacks.

    Setting Up a Page Stack

    First, add a PageStack item as a child to the top-level QML element of your application (usually this is Window). By default, the page stack fills its parent item so, if that is not what you want, you need to resize and anchor the page stack to suit your requirements. For example, you might want to anchor it to a status bar, tool bar, tab bar, or some other similar UI component.

    Once you have a page stack, a common way to load the first page in the stack is to call PageStack.push() from the application's Component.onCompleted() handler.

     Component.onCompleted: {
         pageStack.push(firstPage)
     }

    Creating Pages and Pushing them to the Stack

    Pushing a QML Item Page

    If you define a page as a QML item you can push it to the page stack by referencing its id. In this case, you are pushing a particular page "object" to the stack. Note that the stack takes ownership of the page when you push it and, when you pop the page off the stack, the stack re-parents the page back to its original owner. The stack does not clone or destroy the page object, it just takes ownership for a while. This way, your application always has access to an instance of the class but the class always takes up device memory.

    You push an item-type page to the stack by referencing its id, as shown in the following code snippet.

     pageStack.push(itemPage)

    Pushing a QML Component Page Defined in a Component File

    You can push a page to the stack by referencing the filename of the file that defines the page. When referencing a page by filename, you need to use the Qt.resolvedUrl() method so that the system can find the file.

     pageStack.push(Qt.resolvedUrl("FilePage.qml"));

    Pushing a QML Component Page

    If you define your page as a QML component, when you push a component page to the page stack, the page stack creates an "instance" of the component "class" and pushes that instance object onto the stack. When you pop the page object off the stack, the stack destroys the page object and you no longer have access to it. This means you only have access to the content of the pages that are currently on the page stack. If you want to have persistent data on pages that are popped off the stack, you need to store that data in a model somewhere else. The component-type pages are beneficial when an application has many pages because it makes it possible to manage the memory more efficiently. Only those pages that are currently on the stack need to have memory allocated and when pages are pushed off the stack they are automatically destroyed and the memory held by them gets freed.

    Components are more flexible than items in that you can have any number of instances of pages created from a single component. They are also more powerful if an application has many page types, since those page types don't need to be instantiated when the application starts but rather, you can instantiate them lazily just when the page is used.

    You push a component page by its id, as shown in the following snippet.

     pageStack.push(componentPage);

    Avoiding the "Parent Trap" When Doing a Replace

    If you are using Qt.createComponent() to create and push pages to the page stack, you need to be very careful about who is the parent of the page. When you use Qt.createComponent(), the parent of the created component is the item that called Qt.createComponent(). QML follows the standard Qt parent-child destruction rules so, if the parent item is destroyed the child item is also destroyed. So, if you construct your application in a particular way, you can run into the situation where your page is destroyed "mysteriously". The explanation is that you have fallen into the "parent trap" - the parent was destroyed and so the child was destroyed as well in the cleanup but you are still trying to do something with the child.

    This situation can easily happen in the case of a replace() operation. For example: If item A is already on the page stack and it creates item B with pageStack.replace(Qt.createComponent("B.qml")), A is set as the parent of B. If you then try to replace() A with the newly created B, the page stack first pops A off the stack and destroys it before trying to push B onto the stack. However, since B is a child of A, it is deleted along with A. The page stack then tries to push the now non-existant page B to the stack which, of course, causes problems.

    The following pseudocode demonstrates the sequence of events in the pageStack.replace(Qt.createComponent("B.qml")) operation:

     A.qml                               Qt              PageStack
    
     B = Qt.createComponent("B.qml") --> new(B)
                                         B.parent = A
     <---------------------------------- return B
     pageStack.replace(B) -----------------------------> pop(A)
                                                         A.destroy() // destroys A and its children
                                                             [ B.destroy() ]
                                                         push(B)     // FAILS because B doesn't exist

    You can avoid the "parent trap" problem in a few ways:

    • Use Qt.resolvedUrl("MyPage") instead of Qt.createComponent("MyPage"). With Qt.resolvedUrl() you are pushing a string to the stack rather than a page object. The page stack itself calls Qt.createComponent() to create the page which means the page stack is the parent of the page and therefore you do not have any parent problems to worry about.
    • If you must use Qt.createComponent, reparent the created page with a parent that you know won't be destroyed and then push the page onto the stack. For example, you could set the page stack as the parent as follows:
           var myPage = Qt.createComponent("MyPage.qml")
           myPage.parent = pageStack.parent
           pageStack.replace(myPage)
    • You can also just make sure you create the pages with Qt.createComponents() in a parent that is not going to be destroyed.

    Passing Parameters to Pages

    Normal property bindings should be used whenever possible instead of "passing parameters" from one page to another. However, bindings only work for item type pages. It does not work with component pages because the page instance doesn't exist until it is pushed so its properties are not available to be bound to beforehand. To get around this, you supply a map of properties for the page as the property argument in the push() or replace() function.

    The code below gives an example of pushing a page to the page stack and setting a property for that page.

         pageStack.push( componentPage, {message: pageStack.depth+1});

    If you want to push multiple pages at once to the stack with parameters for each page, you push an array of pages onto the stack and specify a property map with each page in the array. The code snippet below gives an example of this.

         pageStack.push([
             {page: componentPage, properties: {message: pageStack.depth+1}},
             {page: componentPage, properties: {message: pageStack.depth+2}},
             {page: componentPage, properties: {message: pageStack.depth+3}}])

    Page-to-Page Transition Animations

    PageStack automatically provides appropriate transition animations as the user moves from one page to another. The type of animation that occurs is fixed according to the user interface guidelines for the platform and cannot be customised.

    For example, to move deeper into the application, you push a new page onto the stack and the platform-specific push animation is played. When moving back to the previous page, you pop the current page off the stack and the platform-specific pop animation is played.

    Enabling the ToolBar

    If an application page is based on the Page component you can define page- specific tools (see Page::tools) to populate the tool bar. Then, so long as you specify a PageStack::toolbar container, PageStack automatically populates the tool bar with the tools for the current page. If a page does not have any tools, the tool bar is hidden when that page is visible.

    PageStack also automatically handles the tool bar transition animations. The animations for tool bars are not necessarily identical to the transition animations for pages, but they are an appropriate match and are implemented according to the platform's user interface guidelines.

    Navigating with the Page Stack (Easy Method)

    The topmost item in the page stack is the page that is "active" and is visible on the screen. To move to a different page, use the three primary navigation methods in PageStack: push, pop and replace.

    • Forward/push() adds an item to the top of the stack. From the user perspective, this is navigating forward or deeper into the application.
    • Backward/pop() removes the top item from the stack. From a user perspective, this is navigating back to the previous page.
    • Replace/replace() is like a pop followed by a push in that it replaces the topmost item on the stack with a new item. From a user perspective, this is a sideways movement rather than forwards or backwards, the current page is replaced with a page of similar information.

    Example of Basic PageStack Operations

    Given a starting stack of pages [A, B, C], the following example shows the state of the stack after particular operations.

    1. push(D) => [A, B, C, D] - "push" transition animation between C and D
    2. pop() => [A, B] - "pop" transition animation between C and B
    3. replace(D) => [A, B, D] - "replace" transition between C and D
    4. pop(A) => [A] - "pop" transition between D and A

    Navigating with the PageStack (Advanced Method)

    PageStack also supports advanced variations of the push, replace and pop operations for moving several steps forward or backward at a time, or for starting your application with a pre-defined stack of pages.

    • Move several steps backward/unwind: Sometimes it is necessary to go back more than a single step in the stack. For example, you might want to return to the application's main page or some other significant intermediate page. In this case you can provide pop() with a particular page to pop to. This is called "unwinding" the stack. If the page you specify in the pop() function is not found, the stack unwinds until there is only a single page in the stack. However, if you want to explicitly unwind to the bottom of the stack, it is best to just use pop(null).
    • Move several steps forward: If you want to jump forward to a particular place in the application hierarchy, you can push() an array of pages to the stack. No matter how many pages you push, the transition animation is performed only as the new current page is shown and not for intermediate pages.
    • Sidestep and forward: You can also replace() the current page with an array of pages. For the user, this is like stepping sideways in the application hierarchy and then taking a few steps deeper.
    • Startup application at a pre-navigated point: Sometimes you want to start your application in a particular state. For example, you could launch a newspaper application and show a particular article, bypassing the front page and navigation pages that you normally have go through to get to the article. To achieve this, you push an array of pages onto the stack at startup instead of a single page. The array contains the set of pages that the user normally goes through to navigate to the required page.
    • Change to a particular state: If you want to change your application to a quite different state, you can clear() the stack and then push() an array of pages with the new application state.

    Example of Advanced PageStack Navigation

    Given a starting stack of pages [A, B, C, D, E], the following example shows the state of the stack after particular operations.

    1. pop(C) => [A, B, C] - "pop" animation between E and C
    2. push([D, E, F]) => [A, B, C, D, E, F] - "push" transition animation between C and F
    3. replace([D, E, F] => [A, B, D, E, F] - "replace" transition animation between C and F
    4. clear(); push([D, E, F]) => [D, E, F] - no transition animation (since the stack was empty)
    5. clear(); replace([D, E, F]) => [D, E, F] - no transition animation

    Finding a Page in the Stack

    Sometimes it is necessary to search for a page so that you can unwind the stack to a particular page you do not have a reference to. PageStack's find() function allows you to do this.

    The code snippet below shows how to unwind the stack to a page where the message property is "2". However, if a page with a message value of "2" is not found, the stack is unwound to the bottom and the first page in the stack will be the new current page. This happens because, when no matching page is found in the stack, the find() function returns null. This means null is passed to the pop() function which then has the effect of unwinding the stack right to the bottom.

         pageStack.pop(pageStack.find(function(page) {
                                          return page.message == "2";
                                      }));

    Improving Performance

    Sometimes the application needs to take the user to a point deep in the hierarchy without having to navigate there step by step. This requires pushing a lot of pages to the stack at once which can take a significant amount of time and will show up as an interruption in the user interface.

    To reduce the amount of time it takes to show the new page, you can use PageStack in a particular way: instead of specifying the particular QML objects to load, you specify the URL of each page to push or replace. This way, PageStack loads the page components for the intermediate pages (not the actual content) and only instantiate the page that becomes active.

    See also Page and Pages and navigation.

    Property Documentation

    busy : bool

    This is true if there is an ongoing transition between pages on the stack. Otherwise false.


    currentPage : Item

    The page in the stack that is currently visible.


    depth : int

    The number of pages on the page stack.


    toolbar : ToolBar

    The toolbar container for the tools associated with each page. If a toolbar is specified, the tools set for the current page is shown to the user.

    If toolbar is null, then no tools are shown even if a page does have tools.

    See also Page::tools.


    Method Documentation

    PageStack::clear ()

    Clears the page stack of all pages.


    PageStack::find ( function )

    This iterates, top to bottom, through all the pages in the page stack and passes each page to the given function. If the specified function returns true, the iterating stops and this function returns the page that produced the true result. If no matching page is found in the page stack, null is returned.


    PageStack::pop ( page, immediate )

    When you use pop() with no arguments, it pops the top page off the stack and returns that page to the caller. The normal pop transition animation is performed. If the page popped off the stack is based on the Item element, the page is re-parented back to its original parent.

    If you give a page argument, the stack is unwound to the given page. Any Item-based pages popped off the stack are re-parented to their original parent.

    If the given page is not found in the stack, the stack is unwound to the first page in the stack. However, if you specifically want to unwind the page stack to the first page in the stack, it is best to be explicit about what you are doing and use pop(null) rather than guessing a page that is not on the stack.

    The immediate argument defaults to false which means the normal transition animation is performed when a page is popped. If you do not want the transition animation to be performed pass a value of true for immediate.

    Note: A pop() on a stack with that contains 0 or 1 pages is a no-operation.

    Returns: The page that was top-most on the stack before the pop operation.


    PageStack::push ( page, properties, immediate )

    Pushes the given page onto the page stack. You can use a component, item or string for the page. If the page is based on the Item element, the page is re-parented. If a string is used then it is interpreted as a URL that is used to load a page component. The push operation results in the appropriate transition animation being run. If you are pushing an array of pages, the transition animation is only shown for the last page.

    Returns: The new top page on the stack.

    The page argument can also be an array of pages. In this case, all the pages in the array are pushed onto the stack. The items in the array can be components, items or strings just like for pushing a single page.

    The page argument can also be an object that specifies a page with properties or even an array of pages with properties.

    The properties argument is optional and allows you to specify values for properties in the page being pushed.

    The immediate argument defaults to false which means the normal transition animation is performed when a page is pushed. If you do not want the transition animation to be performed pass a value of true for immediate.

    Note: When the stack is empty, a push() or replace() does not perform a transition animation because there is no page to transition from. The only time this normally happens is when an application is starting up so it is not appropriate to have a transition animation anyway.

    See also Page.


    PageStack::replace ( page, properties, immediate )

    Replaces the top-most page on the stack with page. As in the push() operation, you can use a component, item or string for the page, or even an array of pages. If the page is based on the Item element, the page is re- parented. As in the pop() operation, the replaced page on the stack is re- parented back to its original parent.

    Returns: The new top page on the stack.

    See also push().