Complex QML UI questions



  • We are beginning the creation of a fairly complex user interface and would like to accomplish the following:

    In order to avoid the entire UI being placed in one QML file with an unreasonable amount of "states" we would like to embed QML elements into a larger QML file where each item is a separate document. For instance, if we were creating an automotive dashboard we would have a speedometer QML file that controlled all the UI elements relating to the speedometer. This would sit in the larger dashboard UI along with the odometer qml file, etc.

    Does this make sense? What code will accomplish this?

    Also, how can I navigate between different QML UI pages? For instance in the dashboard example the setup pages would link to one another as the menu system is traversed.



  • Yes, it makes sense. If you will split elements in different files you can work with them like with standard qml components and reuse them as many times as you want.
    Navigation between qml pages can be done via flippable or via moving old page off the screen and moving new page to screen.



  • Could you provide more code detail. I am not surprised that it is possible, but I am at a loss for how to begin implementing both of these features.



  • Both of them are well described in qml examples and demos. Just take twitter demo and look into it. Both techniques are used there.



  • So I am looking at the twitter example and I am trying to figure out how they embedded qml files into the larger qml document.

    In twitter.qml is the "import "TwitterCore" 1.0 as Twitter" used to identify the folder? What is the 1.0?



  • 1.0 is version.
    TwitterCore here is folder and Twitter is alias for qmls in this folder. This alias is used in twitter.qml.



  • So I tried creating my own folder and naming in a similar structure but it doesn't seem to work. I guess I will keep experimenting.



  • have you created qmldir file?



  • maybe this will help you: "http://doc.qt.nokia.com/4.7/qdeclarativedocuments.html":http://doc.qt.nokia.com/4.7/qdeclarativedocuments.html

    but like Denis said you should look at flickr, twitter demos



  • "http://doc.qt.nokia.com/4.7/qdeclarativemodules.html":http://doc.qt.nokia.com/4.7/qdeclarativemodules.html is a good place to start for the import statement. In general, reading through the overviews at "http://doc.qt.nokia.com/4.7/qtquick.html":http://doc.qt.nokia.com/4.7/qtquick.html should give you a good introduction to QML.



  • Isn't the qmldir part of the .qmlproject file?



  • What I cannot figure out in any example is whether I can navigate from something like a mainpage.qml to a settings.qml and keep them wholly separate. Is this possible?

    I look forward to a book or other resource where I can learn from ground up. Combing through examples has not proved to be super helpful yet.

    Thanks,

    Kyle



  • I just found the qmldir file in the Twitter example. It is only visible in the project directory and not in Qt Creator at all.


  • Moderators

    kyleplattner: I am no quick expert, but I think I remember the filenames being case sensitive. So if you have a Button, then that should go into a Button.qml, not in button.qml.



  • Tobias,
    That solved one of my issues. Thanks,

    Kyle



  • I still am sketchy on how to cleanly navigate between separate qml documents.



  • OK. let me know if this works for you. I also started using qml so I'm at a very rookie level , if anyone has a better solution can correct me any time.

    you have 3 files: main.qml, Page1.qml, Page2.qml

    If I understand correct you want to move from page1 to page2. when you press the rectangle from page1 you will go to page 2 and the same way around. You can also use "transitions":http://doc.qt.nokia.com/4.7/qdeclarativeanimation.html#transitions for a more animated effect

    here is the code:

    main.qml

    @import Qt 4.7

    Rectangle {
    id:main_rectangle
    width: 360
    height: 640

    Page1{
        id:page1
    }
    
    Page2{
        id:page2
    }
    
    states: [
        State {
            name: "page2"
            PropertyChanges { target: page1; visible:false; }
            PropertyChanges { target: page2; visible:true; }
        },
        State {
            name: "page1"
            PropertyChanges { target: page2; visible:false; }
            PropertyChanges { target: page1; visible:true; }
        }
    
    ]
    

    }
    @

    Page1.qml

    @import Qt 4.7

    Rectangle {

    width: 360
    height: 640
    
    Text {
        id: myText
        x: 93
        y: 152
        width: 80
        height: 20
        text: "page 1"
    }
    
    Rectangle {
        id: rectangle1
        x: 93
        y: 216
        width: 100
        height: 100
        color: "#912121"
    
        MouseArea {
            id: mouse_area1
            anchors.fill: parent
            onClicked: main_rectangle.state="page2"
        }
    }
    

    }
    @

    Page2.qml

    @import Qt 4.7

    Rectangle {
    width: 360
    height: 640
    visible: false;

    Text {
        id: myText
        x: 93
        y: 152
        width: 80
        height: 20
        text: "page 2"
    }
    
    Rectangle {
        id: rectangle1
        x: 93
        y: 216
        width: 100
        height: 100
        color: "#912121"
    
        MouseArea {
            id: mouse_area1
            anchors.fill: parent
            onClicked: main_rectangle.state="page1"
        }
    }
    

    }
    @



  • Thanks so much, I look forward to trying this. This ran fine on your end?



  • [quote author="kyleplattner" date="1287845568"]Thanks so much, I look forward to trying this. This ran fine on your end?[/quote]

    yes. it runs ok on my side. you load the main.qml file and click the rectangle



  • You are very helpful. Let me know if you find any great QML resources for learning.



  • Also a better example is to create, destroy the QML objects instead of make them not visible.

    @function loadPage1() {
    var component = Qt.createComponent("Page1.qml");
    if (component.status == Component.Ready) {
    var page = component.createObject(main_rectangle);
    }
    }

    @

    and on MouseArea you do something like this:

    @ onClicked: loadPage1();@



  • When I do the later example I return a "ReferenceError: Can't find variable: loadPage1" error. Do I need to make a qmldir file? Will Qt creator auto-generate one for me?

    Kyle



  • you need to put the mousearea on main.qml and you don't need to create the 2 objects Page1 and Pgae2. you will create after the button is pushed



  • In this example, if I wanted to make a button that loaded from a separate QML file as button.qml, why can't I do something like this:

    @import Qt 4.7

    Rectangle {
    property alias text: textItem.text
    var page = "page2"

    if (page2.visible == true)
    {
    
    page = "page1"
    
    }
    
     width: 100; height: 30
     border.width: 1
     radius: 5
     smooth: true
    
     gradient: Gradient {
         GradientStop { position: 0.0; color: "lightGray" }
         GradientStop { position: 0.5; color: "gray" }
         GradientStop { position: 1.0; color: "lightGray" }
     }
    
     Text {
         id: textItem
         anchors.centerIn: parent
         font.pointSize: 20
         color: "white"
         font.family: "Helvetica Neue"
     }
    
     MouseArea {
         id: mouse_area_button
         anchors.fill: parent
         onClicked: main_rectangle.state = page
     }
    

    }
    @



  • you example is for button.qml ? or for the main.qml?



  • button.qml



  • ok so do you receive any error? you defined the page2 in main.qml?



  • I am trying to figure out a way for the button to know what page should be navigated to based on what page it is currently on. For instance, if it is on page 1 then it should navigate to page 2 and if it is on page 2 it should navigate to page 1. That is what I was trying to accomplish but it threw me errors.



  • ok. but the button where it is build? in main page, page1 or page 2. because if it's build in main page and when you press it you load page1 for example then the button will probably become invisible. if the button is build in page1 or page2 you already know what is the current page. can you post the entire code for every qml page to make a better idea.



  • It is loaded in each page file:

    main.qml
    @import Qt 4.7

    Rectangle {
    id:main_rectangle
    width: 640
    height: 480

    /* function loadPage1() {
    var component = Qt.createComponent("Page1.qml");
    if (component.status == Component.Ready) {
    var page = component.createObject(main_rectangle);
    }
    }
    */

    Page1{
        id:page1
    }
    
    Page2{
        id:page2
    }
    Page3{
        id:page3
    }
    Page4{
        id:page4
    }
    Page5{
        id:page5
    }
    
    states: [
        State {
            name: "page5"
            PropertyChanges { target: page1; visible:false; }
            PropertyChanges { target: page2; visible:false; }
            PropertyChanges { target: page5; visible:true; }
            PropertyChanges { target: page4; visible:false; }
            PropertyChanges { target: page3; visible:false; }
        },
        State {
            name: "page4"
            PropertyChanges { target: page1; visible:false; }
            PropertyChanges { target: page2; visible:false; }
            PropertyChanges { target: page5; visible:false; }
            PropertyChanges { target: page4; visible:true; }
            PropertyChanges { target: page3; visible:false; }
    
        },
        State {
            name: "page3"
            PropertyChanges { target: page1; visible:false; }
            PropertyChanges { target: page2; visible:false; }
            PropertyChanges { target: page5; visible:false; }
            PropertyChanges { target: page4; visible:false; }
            PropertyChanges { target: page3; visible:true; }
    
        },
        State {
            name: "page2"
            PropertyChanges { target: page5; visible:false; }
            PropertyChanges { target: page4; visible:false; }
            PropertyChanges { target: page3; visible:false; }
            PropertyChanges { target: page1; visible:false; }
            PropertyChanges { target: page2; visible:true; }
        },
        State {
            name: "page1"
            PropertyChanges { target: page5; visible:false; }
            PropertyChanges { target: page4; visible:false; }
            PropertyChanges { target: page3; visible:false; }
            PropertyChanges { target: page2; visible:false; }
            PropertyChanges { target: page1; visible:true; }
        }
    
    ]
    

    }
    @

    page1.qml
    @import Qt 4.7

    Rectangle {

    width: 640
    height: 480
    
    Button { text: "Page Two"; x:50; y:232; }
    Button { text: "Page Three"; x:200; y:232; }
    Button { text: "Page Four"; x:350; y:232; }
    Button { text: "Page Five"; x:500; y:232; }
    

    }
    @

    button.qml
    @import Qt 4.7

    Rectangle {
    property alias text: textItem.text

    //var page = "page2"
    
    
     width: 100; height: 30
     border.width: 1
     radius: 5
     smooth: true
    
     gradient: Gradient {
         GradientStop { position: 0.0; color: "lightGray" }
         GradientStop { position: 0.5; color: "gray" }
         GradientStop { position: 1.0; color: "lightGray" }
     }
    
     Text {
         id: textItem
         anchors.centerIn: parent
         font.pointSize: 20
         color: "white"
         font.family: "Helvetica Neue"
     }
    
     MouseArea {
         id: mouse_area_button
         anchors.fill: parent
         onClicked: main_rectangle.state = "page2"
     }
    

    }
    @

    and every subsequent page (page2.qml, page3.qml, etc) is identical to page 1 with minor logical changes.



  • I got it to work by placing the mouse_area instructions within each specific page. The next question I have is regarding how I can skin my designs using CSS-like files. Is this possible?

    Kyle



  • Also, how can I change the state of my button.qml file from my page1.qml?



  • you just create states in your button.qml file and then you use buttonName.state=stateName



  • So no qmldir file needed? The page1.qml doesn't seem to know that button exists.



  • well didn't you created the button in page1.qml ?? did you gave it an id? you need to pass the button id from page1.qml and not from button.qml



  • another approach will be to use "Loader":http://doc.qt.nokia.com/4.7/qml-loader.html

    Just found out about it. :)



  • Can I create a .config file or the equivalent of a .plist file for the settings menu to write to?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.