Controlling rotation in QML – looked hard, but was easy

I was hunting around the web for an easy way to do rotation in Qt apps, and if possible, QML for an N9 app I’m writing.   I ended up trying various solutions, including using a C++ class and Qt Mobility to handle it and trying to call QtMobility from within QML.  These are things people have said would work and have used it seems, but I was sure there had to be a simpler way.  Now I’m not claiming the way I ultimately used was anything new, and I’m sure many QML app developers have used it before, but once I found it, it was so simple.  That crucial point is that you  create your new app with the base QML object as a PageStackWindow.

The default window for QML apps for Harmattan and Belle is now a PageStackWindow, and doing this gives you some inner objects right out of the bat – a Page called mainPage, and then within the PageStackWindow QML itself, a ToolBarLayout for you to set up the standard app toolbar.  You don’t need to use either of these (although you do need at least one Page for the PageStackWindow) and you can create a a single screen, full screen app just as easily as you can a multi-screen one with the toolbar.

The key to why use a Page StackWindow, even if you don’t want a multi-page app, is one simple property: inProtrait

So this gives you two options: one is to create a Boolean property on your Page and then in your PageStackWindow, assign that property the value of inProtrait. In your page you can then use that property to control a State. Here is the PageStackWindow code for this:

PageStackWindow {
 id: window
 initialPage: myPage
 showStatusBar: true
 showToolBar: true

 ToolBarLayout {
     id: toolBarLayout
         ToolButton {
            flat: true
            iconSource: "toolbar-back"
            onClicked: window.pageStack.depth <= 1 ? Qt.quit() : window.pageStack.pop()
         }
    }
     MainPage {
        id:myPage
        tools: toolBarLayout
        portrait: inPortrait
    }
}

The alternative is if you have different layouts or options in Landscape compared to Portrait that would make it hard to control/re-layout using states. In this case, create 2 Pages, and switch between them when inPortrait Changes, as well as setting the initial Page based on orientation.  In this example I am not using the toolbars provided by default.  The PageStack.Replace method switches the current page at the top of the stack.

PageStackWindow {
    id: appWindow

    onInPortraitChanged: {
        if (inPortrait && pageStack.currentPage!==mainPage)
            pageStack.replace(mainPage);
        else if (!inPortrait && pageStack.currentPage!==mainPageLandscape)
            pageStack.replace(mainPageLandscape);
    }

    initialPage: inPortrait ? mainPage : mainPageLandscape

    PortraitPage {
        id: mainPage
    }

    LandscapePage {
        id: mainPageLandscape
    } 
}

So there you go, a simple ways to control rotation all in QML, allowing your application logic / view models to not have to worry about screen layout and device rotation.

About these ads

About bluechrism

I am a software developer with most professional experience in the Windows .Net realm and I'm currently a WPF developer with Starkey Labs. However, I have wanted for some time to start the mobile developer journey properly and being an N900 owner, this was to be in the realm of QT. Job hunting, moving to Minnesota and changing jobs put my plans on hold 6-12 months but things are starting to settle now, just as I'm getting sorted to start some things, Microsoft and Nokia merge. This blog is about my novice mobile development experiences and hopefully will end up complete with links to download some apps on various platforms, but obviously by the name, Sybian, Maemo/Meego and Windows Mobile. In other stuff, I am English, I support Everton FC, I have visited Glastonbury music festival 5 times and recommend it to anyone. I am married and my wife and i have a dog called Friday.
This entry was posted in Development, MeeGo, Qt, Symbian and tagged , , , , , . Bookmark the permalink.

4 Responses to Controlling rotation in QML – looked hard, but was easy

  1. alfonso says:

    Hi and thank you, this is exactly what I was looking for! :)
    In Qt Creator 2.4.1 (Qt 4.7.4)

    I have a main.qml like this:

    import QtQuick 1.1
    import com.nokia.symbian 1.1

    PageStackWindow {
    id: appWindow

    onInPortraitChanged: {
    if (inPortrait && pageStack.currentPage!==mainPage)
    pageStack.replace(mainPage);
    else if (!inPortrait && pageStack.currentPage!==mainPageLandscape)
    pageStack.replace(mainPageLandscape);
    }

    initialPage: inPortrait ? mainPage : mainPageLandscape

    PortraitPage {
    id: mainPage
    }

    LandscapePage {
    id: mainPageLandscape
    }
    }

    but when I try to run I get the following error:

    file:///C:/Users/VBox/Qt/QMLorientation-build-simulator-Simulator_Qt_for_MinGW_4_4__Qt_SDK__Debug/qml/QMLorientation/main.qml:16:5: PortraitPage is not a type

    do you have any idea of what did I do wrong?

    thank you!

    • bluechrism says:

      For Qt to recognize PortraitPage or LandscapePage you need to add QMl files with those names to the solution in the same folder as main.qml. QML object types are determined by file name so it’s only important that the File Names are PortraitPage and LandscapePage – the id’s internally can be whatever you want. The root QML emlement of those files should be a Page object. For example, adding files called PortraitPage.qml and LandscapePage.qml will show a blue screen in portrait and green in landscape.

      PortaitPage.qml:
      import QtQuick 1.1

      Page {
      id: page1

      Rectangle {
      anchors.fill: page1
      color: “blue”
      }
      }

      LanscapePage.qml
      import QtQuick 1.1

      Page {
      id: page2

      Rectangle {
      anchors.fill: page2
      color: “green”
      }
      }

      And the solution looks something like this:
      SolutionName
      Sources
      QML
      LandscapePage.qml
      main.qml
      PortraitPage.qml
      Other Files

  2. Alfonso says:

    yes! thanks a lot! :)
    it works now (more or less…)
    I’ll start building on top of it.
    thanks again!

  3. Olivier says:

    Hello,

    thanks a lot for this tip. It’s what I need now. :)
    I’m trying to use the “onInPortraitChanged” option. To have it working correctly, I have changed the:
    pageStack.replace(aPage)
    with:
    pageStack.clear()
    pageStack.push(aPage)
    Then all is working as expected. Using the replace seem to work (I see the page changed), but just after the changes, I have a empty page displayed. This mean I see the wanted page for maybe 0.5 second, then a blank page is coming. No problem using clear()/push().

    Any idea?

    Anyway, thanks a lot for your sample. He helped me a lot.


    Olivier

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s