Results 1 to 12 of 12

Thread: Multi 'page' QML application issues with external QML/Javascript

  1. #1
    Join Date
    May 2011
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Multi 'page' QML application issues with external QML/Javascript

    I am working on a multi-page Qt/QML/C++ app.

    The structure is as follows:

    In root folder:
    main.cpp ====> contains the 'main' startup code
    fileio.cpp ====> contains all my file I/O routines
    gpsio.cpp ====> contains my GPS on/off/update routines

    main.qml ====> 'main' window, contains the HeaderRow & FooterRow, with an empty Rectangle ('winRect') filling the available space between the two... includes a 'property alias' for itself as 'appWin'
    HeaderRow.qml ====> contains app title, version, etc... static data
    FooterRow.qml ====> contains navigation buttons: Home, Settings, Upload, Status, Quit
    functions.js ====> contains 'common' javascript functions utilized in all QML files

    "SubPages" folder under the root:
    SubPages/MainWin.qml ====> contains the 'main' interface with GPS start/stop button, various feedback text fields
    SubPages/InfoWin.qml ====> contains 'status' text fields
    SubPages/SettingsWin.qml====> contains application 'settings'
    SubPages/UploadWin.qml ====> contains file list for uploading to server

    How it works:
    main.qml uses 'import' on the functions.js and the SubPages folder to get access to all functions and all 'child' windows.
    FooterRow buttons 'load' the required 'page' into the 'winRect' on pressed using a javascript 'loadPage' function:

    Qt Code:
    1. function loadPage(page){
    2. appWin.currentPage = "%1".arg(page);
    3. }
    To copy to clipboard, switch view to plain text mode 

    and in main.qml:

    Qt Code:
    1. // Set this property to another file name to change page
    2. property string currentPage : "SubPages/MainWin";
    3.  
    4. // Put the name of the QML files containing your pages (without the '.qml')
    5. property variant pagesList : [
    6. "SubPages/MainWin",
    7. "SubPages/InfoWin",
    8. "SubPages/SettingsWin",
    9. "SubPages/UploadWin"
    10. ];
    11. Rectangle {
    12. id: winRect
    13. visible: true
    14. anchors.right: parent.right
    15. anchors.left: parent.left
    16. anchors.top: header.bottom
    17. anchors.bottom: footer.top
    18. color: "black"
    19.  
    20. Repeater {
    21. model: pagesList;
    22. delegate: Loader {
    23. active: false;
    24. asynchronous: true;
    25. anchors.fill: parent;
    26. visible: (currentPage === modelData);
    27. source: "%1.qml".arg(modelData)
    28. onVisibleChanged: { loadIfNotLoaded(); }
    29. Component.onCompleted: { loadIfNotLoaded(); }
    30.  
    31. function loadIfNotLoaded () {
    32. // to load the file at first show
    33. if (visible && !active) {
    34. active = true;
    35. }
    36. }
    37. }
    38. }
    39. }
    To copy to clipboard, switch view to plain text mode 

    The issues I am having...

    1. Each child page is set up with all its components spaced according to the overall size of the 'parent', which is 'winRect'. However, on loading a child page, I get warnings about not being able to anchor to winRect, as it's not really the parent of the child. So, how can I make winRect the parent of each child page?

    2. In main.qml, I use "import 'SubPages'" to get access to the child pages. But, if I try to do anything in main.qml with a page by name (ie. MainWin), I get an error: 'SubPages not defined'... Why?

    3. My javascript functions modify objects on my QML child pages. Or at least, they are supposed to... I get errors about each page not being defined within the javascript function. To get around this, I tried to pass the child page into the function as an argument, but then I get #2 above.

    4. Am I crazy? Is there a better way to create such an application? Do I need to have ALL my child pages defined in the main.qml somehow?

    5. HELP!

    --Sam

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Quote Originally Posted by scgrant327 View Post
    1. Each child page is set up with all its components spaced according to the overall size of the 'parent', which is 'winRect'. However, on loading a child page, I get warnings about not being able to anchor to winRect, as it's not really the parent of the child. So, how can I make winRect the parent of each child page?
    The Loader will resize its item to its own size, so just bind the width/height of each Loader to the rectangle's properties.

    Quote Originally Posted by scgrant327 View Post
    2. In main.qml, I use "import 'SubPages'" to get access to the child pages. But, if I try to do anything in main.qml with a page by name (ie. MainWin), I get an error: 'SubPages not defined'... Why?
    The import gives you access to the elements defined in the QML files in that directory, e.g.
    Qt Code:
    1. MainWin {
    2. }
    To copy to clipboard, switch view to plain text mode 
    If you need namespacing use the "import as" syntax
    Qt Code:
    1. import "SubPages" as SubPages
    2.  
    3. SubPages.MainWin {
    4. }
    To copy to clipboard, switch view to plain text mode 
    Not sure why you need the import at all since you are using Loaders to load them, not direct instantiation.


    Quote Originally Posted by scgrant327 View Post
    3. My javascript functions modify objects on my QML child pages. Or at least, they are supposed to... I get errors about each page not being defined within the javascript function. To get around this, I tried to pass the child page into the function as an argument, but then I get #2 above.
    I am afraid I didn't understand that one.

    Quote Originally Posted by scgrant327 View Post
    4. Am I crazy? Is there a better way to create such an application? Do I need to have ALL my child pages defined in the main.qml somehow?
    As far as I can tell it looks like a good approach for "loading pages on first use"

    Cheers,
    _

  3. #3
    Join Date
    May 2011
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Doing either import "SubPages" or import "SubPages" as SubPages causes the same error, saying that each page I want to access is not defined.

    As I see it, I have to import the pages, because on application startup, my gpsio.cpp function gets the users current location, and then updates the text fields in the MainWin page... BEFORE MainWin is even loaded... via a javascript function that is called from gpsio.cpp:

    Qt Code:
    1. void gpsio::stopOneShotGPS()
    2. {
    3. sourceOneShot->stopUpdates();
    4.  
    5. QObject *root = myFileIO->engine.rootObjects().first();
    6. QVariant returnedVal;
    7. QMetaObject::invokeMethod(root,"gpsOneShotUpdate",Q_RETURN_ARG(QVariant, returnedVal)); ====> calls javascript function to update text fields
    8.  
    9. root->setProperty("myFilePath",myFileIO->myFilePath);
    10. root->setProperty("myProdType", QSysInfo::productType());
    11. root->setProperty("myProdVers", QSysInfo::productVersion());
    12. }
    To copy to clipboard, switch view to plain text mode 

    "gpsOneShotUpdate" is exposed to the C++ via main.qml and defined in functions.js:

    Qt Code:
    1. function gpsOneShotUpdate() {
    2. mainWin.timeLabel.text = "";
    3. mainWin.latLabel.text = appWin.currentLat;
    4. mainWin.lonLabel.text = appWin.currentLon;
    5.  
    6. mainWin.accyLabel.text = "---";
    7. mainWin.hdgLabel.text = "---";
    8.  
    9. mainWin.spdLabel.text = "---";
    10. mainWin.cntLabel.text = "---";
    11. mainWin.statusImage.source = "status_64x128_grey.png";
    12.  
    13. loadPage("SubPages/MainWin");
    14. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Quote Originally Posted by scgrant327 View Post
    Doing either import "SubPages" or import "SubPages" as SubPages causes the same error, saying that each page I want to access is not defined.
    You haven't used any of the elements of that directory in the code you provided so far, so it is hard to tell what could be wrong.

    Quote Originally Posted by scgrant327 View Post
    As I see it, I have to import the pages, because on application startup, my gpsio.cpp function gets the users current location, and then updates the text fields in the MainWin page... BEFORE MainWin is even loaded... via a javascript function that is called from gpsio.cpp:
    Ah, I remember now. You are trying to create an artifically complex situation. Any specific reason for that?

    Cheers,
    _

  5. #5
    Join Date
    May 2011
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Quote Originally Posted by anda_skoa View Post
    You haven't used any of the elements of that directory in the code you provided so far, so it is hard to tell what could be wrong.
    Fair enough. To get where my UI is updated as detailed below, I was trying to pass the QML to my javascript function. So, I import the SubPages folder and pass the MainWin.qml to my javascript, but that results in the MainWin undefined error:

    Qt Code:
    1. function gpsOneShotUpdate() {
    2. Funcs.gpsOneShotUpdate(MainWin)
    3. }
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by anda_skoa View Post
    Ah, I remember now. You are trying to create an artifically complex situation. Any specific reason for that?
    Not trying to complicate things...

    This is for use on mobile devices... On startup, my app needs to get the users location (which is done via a gpsio.cpp function). Once that location is determined, the app needs to update the UI with that location. This initial location needs to be determined before the initial 'Main Window' is visible.

    So... C++ gets location and sets main.qml variables. Then C++ calls main.qml function to update UI on SubPage qml. main.qml function in turn calls javascript function which does the real Text object updates on SubPage qml.

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Quote Originally Posted by scgrant327 View Post
    Fair enough. To get where my UI is updated as detailed below, I was trying to pass the QML to my javascript function. So, I import the SubPages folder and pass the MainWin.qml to my javascript, but that results in the MainWin undefined error:

    Qt Code:
    1. function gpsOneShotUpdate() {
    2. Funcs.gpsOneShotUpdate(MainWin)
    3. }
    To copy to clipboard, switch view to plain text mode 
    You are not passing MainWin.qml but MainWin.
    Did you want to pass an instance of MainWin?

    I.e. you are trying the C++ equivalent of passing a class name as a function argument.

    Quote Originally Posted by scgrant327 View Post
    Not trying to complicate things...
    Well, exporting the values is far easier than to call into QML.

    Quote Originally Posted by scgrant327 View Post
    This is for use on mobile devices... On startup, my app needs to get the users location (which is done via a gpsio.cpp function). Once that location is determined, the app needs to update the UI with that location. This initial location needs to be determined before the initial 'Main Window' is visible.
    So just gather the value and set it as a context property before loading main.qml?

    Quote Originally Posted by scgrant327 View Post
    So... C++ gets location and sets main.qml variables.
    Which is not jsut very uncommon (creating a C++ -> QML dependency instead of just the other way around), it is also more complicated.

    Quote Originally Posted by scgrant327 View Post
    Then C++ calls main.qml function to update UI on SubPage qml. main.qml function in turn calls javascript function which does the real Text object updates on SubPage qml.
    Quite complicated, isn't it?

    Even if values would change after loading the QML, exposing them via properties on an object would still be easier by far.

    The only thing that it is not so easy is to get the equivalent of the return value.
    But you don't seem to either return something from the function nor do you try to use the returned value. Quite puzzling why you even retrieve it.

    Cheers,
    _

  7. #7
    Join Date
    May 2011
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Did you want to pass an instance of MainWin?
    Yes! I guess?

    So just gather the value and set it as a context property before loading main.qml?
    Going to mod my code and load main.qml (and additionally MainWin.qml inside main.qml), and then use the gpsio function to get and set the values. I am already exposing the necessary variables from main.qml to C++, so the gpsio function can update them as needed.

    Which is not jsut very uncommon (creating a C++ -> QML dependency instead of just the other way around), it is also more complicated.
    ...and 100% necessary. In the end, there will be a gpsio function that continuously updates the QML UI with new values.

    The only thing that it is not so easy is to get the equivalent of the return value.
    But you don't seem to either return something from the function nor do you try to use the returned value. Quite puzzling why you even retrieve it.
    The return value is not necessary. It is left over from me just trying to get everything to work....and copy/pasting code from online examples. The return value can and will be deleted.

  8. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Quote Originally Posted by scgrant327 View Post
    Yes! I guess?
    Then you need to pass the id of the instance or the name of the property holding the instance.
    In C++ you would also pass the name of the variable that hold the pointer to the object, not the class name, right?

    Quote Originally Posted by scgrant327 View Post
    I am already exposing the necessary variables from main.qml to C++, so the gpsio function can update them as needed.
    I was talking about exposing the C++ values to QML.

    Quote Originally Posted by scgrant327 View Post
    ...and 100% necessary. In the end, there will be a gpsio function that continuously updates the QML UI with new values.
    Not necessary at all, that is what property bindings are for.

    Quote Originally Posted by scgrant327 View Post
    The return value is not necessary. It is left over from me just trying to get everything to work....and copy/pasting code from online examples. The return value can and will be deleted.
    I see.

    Then it is really unnecessary to call a JavaScript function from C++. Getting a return value is basically the only use case for that.

    Cheers,
    _

  9. #9
    Join Date
    May 2011
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Ok...some progress...

    Property bindings look like they will work fine for my purpose.

    Issues:
    When calling my javascript functions, why can I not access my QML objects? I get errors about the object being undefined. I've tried by using the alias for the object, the id for the object and the QML file name that houses the object....all give the same error.

    AND... do I need to 'import' the parent and SubPages folders into each of my SubPages/*.qml files?
    I ask because if I try to reference an object in SubPages/Page1.qml from SubPages/Page2.qml, I get an error about that object being undefined.

    For instance, when I load SubPages/Page2.qml using the loader I showed earlier. Page2 has a Label that when clicked on will change a value on Page1. But, if I try this I get an error:

    In Page2:
    Qt Code:
    1. MouseArea {
    2. anchors.bottom: parent.bottom
    3. anchors.right: parent.right
    4.  
    5. Label {
    6. id: page2Label
    7. text: qsTr("ClickME")
    8. horizontalAlignment: Text.AlignRight
    9. anchors.top: parent.top
    10. anchors.bottom: parent.bottom
    11. anchors.right: parent.right
    12. anchors.left: parent.left
    13. font.pointSize: 24
    14. color: "lime"
    15. }
    16. onClicked: {
    17. Page1.page1Label.text = page2Label.text
    18. Page1.page1Label.color = "lime"
    19. page2Label.color = "darkred"
    20. }
    21. }
    To copy to clipboard, switch view to plain text mode 

  10. #10
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Quote Originally Posted by scgrant327 View Post
    Property bindings look like they will work fine for my purpose.
    Excellent, bindings on C++ properties is definitely the way to go.
    Way more elegant than making C++ code dependent on QML code.

    Quote Originally Posted by scgrant327 View Post
    When calling my javascript functions, why can I not access my QML objects? I get errors about the object being undefined. I've tried by using the alias for the object, the id for the object and the QML file name that houses the object....all give the same error.
    Can you show such a function and where the objects are defined?

    For example your gpsOneShotUpdate() function should be fine if there is an object with id mainWin in the same file or a property with the name mainWin in the object the function is in.

    Quote Originally Posted by scgrant327 View Post
    AND... do I need to 'import' the parent and SubPages folders into each of my SubPages/*.qml files?
    import allows you access to types, just like includes in C++.
    The current directory, i.e. the directory the current QML file is in, is always implicitly imported.

    In your case you don't need to import SubPages in main.qml since you are using a Loader, you are not instantiating objects of these types directly in QML code.

    Quote Originally Posted by scgrant327 View Post
    I ask because if I try to reference an object in SubPages/Page1.qml from SubPages/Page2.qml, I get an error about that object being undefined.
    Access to objects has nothing to do with imports.

    Quote Originally Posted by scgrant327 View Post
    For instance, when I load SubPages/Page2.qml using the loader I showed earlier. Page2 has a Label that when clicked on will change a value on Page1. But, if I try this I get an error:

    In Page2:
    Qt Code:
    1. onClicked: {
    2. Page1.page1Label.text = page2Label.text
    3. Page1.page1Label.color = "lime"
    4. page2Label.color = "darkred"
    5. }
    6. }
    To copy to clipboard, switch view to plain text mode 
    Page1 is not a valid id nor a valid property name (both need to start with a lower case letter).

    Cheers,
    _

  11. The following user says thank you to anda_skoa for this useful post:

    scgrant327 (24th February 2016)

  12. #11
    Join Date
    May 2011
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    Ok, I ended up declaring non-visible instances of the SubPages in my main.qml. Works pretty well with my custom 'loader' javascript function to show/hide each page on demand.

    Thanks for the help!

  13. #12
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multi 'page' QML application issues with external QML/Javascript

    You really like doing things imperatively :-)

    However, you might want to look into doing things declaratively for future projects, it really pays off and makes things easier.

    Cheers,
    _

Similar Threads

  1. Multi-page application with Qt Designer
    By chiruL in forum Newbie
    Replies: 1
    Last Post: 23rd January 2016, 11:08
  2. Webkit open new javascript Page
    By ShapeShiftme in forum Qt Programming
    Replies: 3
    Last Post: 25th October 2012, 09:46
  3. Multi-page application and QStackedWidget
    By Mek82 in forum Qt Programming
    Replies: 10
    Last Post: 31st October 2010, 23:06
  4. multi page Application
    By ilpaso in forum Qt Programming
    Replies: 2
    Last Post: 3rd September 2010, 10:36
  5. Replies: 3
    Last Post: 25th February 2010, 09:53

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.