Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. One QML component to be used by multiple C++ controller classes
Forum Updated to NodeBB v4.3 + New Features

One QML component to be used by multiple C++ controller classes

Scheduled Pinned Locked Moved QML and Qt Quick
10 Posts 3 Posters 4.8k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bkamps
    wrote on 31 Jul 2012, 09:20 last edited by
    #1

    I have an embedded device that's pretty slow and i want to speed up loading of windows. Let's say I have a complex QML Window that takes some time to load on my embedded device:

    ComplexWindow.qml:
    @
    Rectangle {
    property string title
    // other stuff that takes some time to load.
    }
    @

    I have one main qml file that has several ComplexWindows that are visible by toggling the visible flag:

    Main.qml:
    @
    ComplexWindow { id: inputWindow; title: myInputWindowCppObj.title; visible: myInputWindowCppObj.visible etc }
    ComplexWindow { id: inputSpecialWindow; title: myInputSpecialWindowCppObj.title; visible: ContactListController.visible etc }
    // etc etc
    @

    All my ComplexWindows have the same user interface structure but are used differently by the C++ controller classes. To decrease load times I want to have ONE ComplexWindow in my main qml file and let the C++ controller classes share that one instance of ComplexWindow. Only one ComplexWindow is visible at one time so it could be shared.

    I want to control ONE QML component by several C++ controller classes. Currently I connect the QML ComplexWindows instances and the C++ controller classes by using the setContextProperty method. But I want only one instance of ComplexWindow being used by all my c++ controller classes.

    Can I somehow (without showing errors in the log):

    • Connect the QML/C++ binding when a c++ controller class is activated. For example a user opens the application menu and decides to open a certain window. Then a c++ controller classes is called and the QML/C++ binding is set. So now the c++ controller classes can control the QML ComplexWindow. When the user decides to leave the window the c++ controller class unbinds itself from QML ComplexWindow instance.

    I have noticed that when in the QML files a property is being binded to a none existing c++ "slot" i receive errors that it cannot bind the property. When I want to share my QML ComplexWindow instance by several c++ controller classes I will have the problem of properties not being binded.

    Does anyone have a suggestion?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      chriadam
      wrote on 31 Jul 2012, 23:49 last edited by
      #2

      I'm not entirely certain that I've understood correctly (regarding your wish to reuse a single component; I personally would probably use a Loader and then set enabled and visible to false when not using one, but perhaps that doesn't work in your use case) but to set up dynamic bindings and signal connections, you can use the Binding and Connections elements, respectively. You can dynamically retarget those, and so you can do it at runtime.

      Cheers,
      Chris.

      1 Reply Last reply
      0
      • B Offline
        B Offline
        bkamps
        wrote on 6 Aug 2012, 05:15 last edited by
        #3

        My apologies for this late reply!

        bq. I personally would probably use a Loader and then set enabled and visible to false when not using one, but perhaps that doesn’t work in your use case) bq.

        I already use loaders to load / unload QML files but my hardware device is pretty slow so loading/parsing the files takes a long time. This is irritating for the user because he has to wait for a window to be visible...

        Now I already have a lot of QML Windows and QML controllers so I thought maybe I need to limit the nr of QML windows to one. Then let a C++ controller set the contextproperties to that qml window whenever it's used. This way I don't need to load a QML file.

        bq. You can dynamically retarget those, and so you can do it at runtime. bq.

        How do you retarget those things from C++? Currently I use the setContextProperty to connect C++/QML but how do i unset a contextproperty? So when a controller is done controlling the QML window how do you "unset" the contextproperties? I tried to set it to null (setContextProperty("mycppObj.test", NULL) but I get an error.

        1 Reply Last reply
        0
        • C Offline
          C Offline
          chriadam
          wrote on 6 Aug 2012, 07:27 last edited by
          #4

          I may have completely misunderstood what you are attempting to do with the controller, but lets say you want to dynamically set up bindings when some context properties change:

          @
          Item {
          id: root
          width: 300
          height: 300

          property Item currentWindow
          
          Binding {
              id: widthBinding
              target: currentWindow
              property: "x"
              value: (root.width / 2) // or whatever bindings you want to be dynamic
          }
          
          onCurrentWindowChanged: widthBinding.target = currentWindow // might not be required
          

          }
          @

          I just mean that as you dynamically change whichever window is your current window, you can create dynamic bindings which will ensure that your ui elements are placed correctly.

          Similarly, for signal connections, you can use the Connections element.

          Cheers,
          Chris.

          1 Reply Last reply
          0
          • B Offline
            B Offline
            bkamps
            wrote on 6 Aug 2012, 11:19 last edited by
            #5

            That's not completely what i'm looking for:

            QML:
            @
            Window {
            visible: myCppObj.visible
            // other bindings
            }
            @

            C++ base class for window:
            @
            class BaseWindow : public QObject {
            Q_OBJECT
            Q_PROPERTY(bool visible READ Visible NOTIFY VisibleChanged)
            public:
            MyWindow::MyWindow() {}
            void SetVisible(....);
            // signals
            // slots
            @

            C++ derived class:
            @
            class DerivedWindow : public QObject {
            public:
            DerivedWindow::DerivedWindow() {}
            void RegisterQml() { mDeclarativeContext->setContextProperty("myCppObj",this); }
            void DereigsterQml() ??????
            }
            @

            C++ derived class two:
            @
            class DerivedTwoWindow : public QObject {
            public:
            DerivedTwoWindow::DerivedTwoWindow() {}
            void RegisterQml() { mDeclarativeContext->setContextProperty("myCppObj",this); }
            void DereigsterQml() ??????
            @

            Ok, so now I have one QML window and two C++ controller classes that want to control the QML window (not simultanously).

            User opens first window and closes it:
            @
            DerivedWindow lWIndow;
            lWindow.Register();
            lWIndow.Show(); // Show QML window
            lWindow.Deregister(); // Decouple QML/C++ binding
            @

            Then user opens second window:
            @
            DerivedTwoWindow lWindow2;
            lWindow2.Register();
            lWindow2.Show();
            lWindow2.Deregister();
            @

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mbrasser
              wrote on 7 Aug 2012, 06:59 last edited by
              #6

              [quote author="bkamps" date="1344230102"]So when a controller is done controlling the QML window how do you "unset" the contextproperties? I tried to set it to null (setContextProperty("mycppObj.test", NULL) but I get an error.
              [/quote]

              What error were you seeing? Are you wanting to unset myCppObj as a whole, or just some of it's sub properties? Note that if you are unsetting the object itself, the QML would need conditional checks to prevent errors, e.g. checks like:

              @visible: myCppObj ? myCppObj.visible : false@

              Easier might be a DummyWindow that could be set in DeregisterQml(), e.g.

              @void UnregisterQml() { mDeclarativeContext->setContextProperty("myCppObj",dummyWindow); }@

              This "window" would have sensible defaults for the properties when there was no real window controlling the QML, and would prevent the need for the conditional checks in the QML.

              Does that make sense for what you are trying to do?

              Regards,
              Michael

              1 Reply Last reply
              0
              • B Offline
                B Offline
                bkamps
                wrote on 7 Aug 2012, 07:59 last edited by
                #7

                bq. What error were you seeing? Are you wanting to unset myCppObj as a whole, or just some of it’s sub properties? Note that if you are unsetting the object itself, the QML would need conditional checks to prevent errors, e.g. checks like:

                bq.

                I am setting the properties. When i do a setContextProperty("mycppObj", null) I get the following error:

                @TypeError: Result of expression 'model' [null] is not an object.@

                This is because I set the object to null and have to do the null check in qml like you showed me... I guess I will get this thing to work.

                Firstly I will try to get two controllers to control one QML window (independently) by resetting the C++/QML bindings.

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  bkamps
                  wrote on 9 Aug 2012, 11:48 last edited by
                  #8

                  bq. 1.visible: myCppObj ? myCppObj.visible : false bq.

                  When I use this construction I get a ReferenceError:

                  @
                  ReferenceError: Can't find variable: myCppObj
                  @

                  Ofcourse this is true because the C++/QML binding isn't done yet...

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mbrasser
                    wrote on 9 Aug 2012, 22:57 last edited by
                    #9

                    You could also try the following:

                    @visible: (typeof(myCppObj) != "undefined") ? myCppObj.visible : false@

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      bkamps
                      wrote on 10 Aug 2012, 18:32 last edited by
                      #10

                      This worked for me:

                      @
                      visible: ((typeof(myCppObj) != "undefined") && myCppObj) ? myCppObj.visible : false
                      @

                      Thanks a lot! I don't like how the code looks but it works :)

                      1 Reply Last reply
                      0

                      1/10

                      31 Jul 2012, 09:20

                      • Login

                      • Login or register to search.
                      1 out of 10
                      • First post
                        1/10
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved