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. Inline component in a component
Qt 6.11 is out! See what's new in the release blog

Inline component in a component

Scheduled Pinned Locked Moved QML and Qt Quick
23 Posts 4 Posters 21.4k 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.
  • T Offline
    T Offline
    Tipiak
    wrote on last edited by
    #1

    Hi,

    Basically, i've got the following code:

    TestPage.qml

    @
    item {
    id: item1
    Component {
    id: inneritem
    TestPage {
    }
    }
    }
    @

    The goal here is to instantiate the inner TestPage dynamically, with a Loader or something else, doesn't matter.

    And when a try to run and use my TestPage somewhere I've got the error: "TestPage is instantiated recursively"

    Well, i believed that when declared in a Component, an Item is not instantiate until we load it with a loader or a bunch of C++ lines (my case).

    I think it's a bug or a limitation. You cannot build recursive item like a treeView or something like that.
    Are there workarounds or scheduled improvement ?

    .signature

    1 Reply Last reply
    0
    • G Offline
      G Offline
      goetz
      wrote on last edited by
      #2

      You embed a TestPage in a TestPage
      This would embed another TestPage in the second TestPage
      Which would subsequently embed a fourth TestPage in the third one
      And that would lead to embedding a fifth one in the fourth TestPage
      Eventually leading to...

      That's the point of that "instantiated recursively" error message.

      Ah.. and when you "run" that snippet, how would that work out without instantiating the component(s)?

      http://www.catb.org/~esr/faqs/smart-questions.html

      1 Reply Last reply
      0
      • T Offline
        T Offline
        Tipiak
        wrote on last edited by
        #3

        Thx for the reply.

        I know what i did.
        That's why a put the inner TestPage in a component, to tell qml to not instantiate the inner TestPage until i told it so.
        It don't really matter which way i used to instantiate it (loader, qt.createObject or in c++ code), the snippet is just a really quick en simple example to made myself clear. it's obvious my real problem is a bit more complex but it's irrelevant here.
        The fact here is that qml complain about a recursive intantiation but, afaik and if i understand what the qml component element says, it shouldn't.

        .signature

        1 Reply Last reply
        0
        • G Offline
          G Offline
          goetz
          wrote on last edited by
          #4

          If it complains about recursive instantiation, it is instantiated recursively. Point.

          And from what I see on the code, this is not even a subtle, hidden error but more than obvious.

          You do nothing else than:

          @
          class Foo {
          public:
          Foo() {
          Foo *x = new Foo;
          }
          };
          @

          http://www.catb.org/~esr/faqs/smart-questions.html

          1 Reply Last reply
          0
          • T Offline
            T Offline
            Tipiak
            wrote on last edited by
            #5

            Nope.

            It would be true if i did:
            @
            TestPage {
            id: testPage
            TestPage {
            id: innerTestPage
            }
            }
            @

            It's not the same thing. If a replace TestPage in the Component of my first example by any other item,
            the item is not instantiate before i manually load it.

            At least the Component.oncompleted signal is not emitted. And I checked with a written c++ Item and the ctor of is not called either until, again, i dynamically load it with a loader on anything else.

            .signature

            1 Reply Last reply
            0
            • G Offline
              G Offline
              goetz
              wrote on last edited by
              #6

              Isn't an element that is not part of the QML core (TestPage) tried to be loaded from a file with that name + .qml (TestPage.qml)?

              http://www.catb.org/~esr/faqs/smart-questions.html

              1 Reply Last reply
              0
              • T Offline
                T Offline
                Tipiak
                wrote on last edited by
                #7

                Yes it is.
                I mean i call the TestPage which is in TestPage.qml, let's say, in Main.qml:

                @
                Item {
                height: 480
                width: 640

                TestPage {
                    anchors.fill: parent
                }
                

                }
                @
                And got the "recursive error".
                what's your point ?

                .signature

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  goetz
                  wrote on last edited by
                  #8

                  Then look at your code and guess what happens on line 5 if you put this into a file called TestPage.qml

                  @
                  item {
                  id: item1
                  Component {
                  id: inneritem
                  TestPage {
                  }
                  }
                  }
                  @

                  http://www.catb.org/~esr/faqs/smart-questions.html

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    Tipiak
                    wrote on last edited by
                    #9

                    okay, my bad. Your snippet is exactly what i wanted to wrote.

                    But i still don't understand why i cannot do that.

                    it's exactly like:
                    @
                    class toto {
                    public:
                    typedef toto innertoto;
                    };
                    @

                    My real problem is that I need an id on a type to be able to pass a Component as a parameter of a script function (which is binded to c++ method). And did not figured how to do that unless i a use a Component.

                    .signature

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      goetz
                      wrote on last edited by
                      #10

                      Problem is to use the component TestPage within the file TestPage.qml.

                      I don't know what's in that inner TestPage, I'd try to rename it. And it seems that you need some second component for the inner part.

                      You can not use a component within itself.

                      Your C++ example is a different thing. You just declare an alias there, but in line 5 of the snippet, you ask the system to instantiate a component of type TestPage. It is not an alias!

                      PS: the snippet is just a copy from your first post.

                      http://www.catb.org/~esr/faqs/smart-questions.html

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        Tipiak
                        wrote on last edited by
                        #11

                        [quote author="Volker" date="1301665037"]Problem is to use the component TestPage within the file TestPage.qml.[/quote]

                        So what? It's in a Component, why i couldn't use it inside. I could understand if the error was something like "Undefined type" but it's not. it says "recursive instantiation" which is definitely not.

                        [quote author="Volker" date="1301665037"]
                        I don't know what's in that inner TestPage, I'd try to rename it. And it seems that you need some second component for the inner part.[/quote]

                        Actually it's a hack. Basically I need an id on a type for giving it to a javascript call binded on a c++ method, because typename are not resolved into component in javascript scope.

                        [quote author="Volker" date="1301665037"]
                        You can not use a component within itself.
                        [/quote]
                        Again, why not ? :)

                        [quote author="Volker" date="1301665037"]
                        Your C++ example is a different thing. You just declare an alias there, but in line 5 of the snippet, you ask the system to instantiate a component of type TestPage. It is not an alias!
                        [/quote]
                        Agreed, but not for the instantiate part. At least that's what l wanted to understand. An inline Component is not an instance, but a unnamed type definition/declaration, with an id thought.

                        @
                        class toto {
                        public:
                        typedef toto innertoto;
                        innertoto *t_;
                        }
                        @
                        I've got the right to initialize the t_ wheneverr i want, way after the the call to toto::ctor() and with my own value. But actually that's not really my problem. I just want the typename to allow me to create it dynamically.

                        [quote author="Volker" date="1301665037"]
                        PS: the snippet is just a copy from your first post.[/quote]

                        It look like it's friday today, i got confused with my second example.

                        .signature

                        1 Reply Last reply
                        0
                        • G Offline
                          G Offline
                          goetz
                          wrote on last edited by
                          #12

                          The discussion is becoming recursive now. I'm giving up to prevent a brain dump...

                          Maybe some Qt Quick experts can explain things more precisely.

                          http://www.catb.org/~esr/faqs/smart-questions.html

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            giesbert
                            wrote on last edited by
                            #13

                            Hi all,

                            I red a bit about "QML and component":http://doc.qt.nokia.com/4.7/qml-component.html :

                            bq. Defining a Component is similar to defining a QML document. A QML document has a single top-level item that defines the behaviors and properties of that component, and cannot define properties or behaviors outside of that top-level item. In the same way, a Component definition contains a single top level item (which in the above example is a Rectangle) and cannot define any data outside of this item, with the exception of an id (which in the above example is redSquare).

                            For me that sounds like:

                            When you instantiate a component TestPage and a file Testpage.qml exists, the object inside the component definition is created. This means a component of type testPage which is located inside a qml file, ...

                            This is definitly a recursion, if you start instatiation.

                            So for me it looks like this in qml:

                            @
                            item {
                            id: item1 // per definition in docs not needed !
                            Component {
                            id: inneritem
                            TestPage {
                            }
                            }
                            }
                            @

                            is the same as this in C++

                            @
                            class Foo
                            {
                            public:
                            Foo() {}

                            Foo innerItem;
                            

                            };
                            @

                            innerItem is not a pointer, that might be instantiated somewhen. Its the object itself which is created as component!

                            Nokia Certified Qt Specialist.
                            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                            1 Reply Last reply
                            0
                            • T Offline
                              T Offline
                              Tipiak
                              wrote on last edited by
                              #14

                              thx for you reply.

                              bq. Notice that while a Rectangle by itself would be automatically rendered and displayed, this is not the case for the above rectangle because it is defined inside a Component. The component encapsulates the QML elements within, as if they were defined in a separate QML file, and is not loaded until requested (in this case, by the two Loader objects).

                              Extracted from the same page.

                              So, as far as i understand, a Component is just a qml file which i define a new component, as the doc says. The doc explicitly tell the component is not rendered until is explicitly load. Therefore, it really look likes a c++ pointer you assigned when you wanted to.

                              Actually, it's really the "recursive instantiation" that bugs me. The more i look at it the more i feel is just a bad check in the qml engine.
                              The doc says a Component is a qml file. So a component definition not an instantiation.

                              .signature

                              1 Reply Last reply
                              0
                              • G Offline
                                G Offline
                                goetz
                                wrote on last edited by
                                #15

                                But once YOUR TestPage is instantiated, it would instantiate another TestPage within the first one!

                                This IS recursion, believe it or not.

                                The compiler is always rightâ„¢.

                                http://www.catb.org/~esr/faqs/smart-questions.html

                                1 Reply Last reply
                                0
                                • G Offline
                                  G Offline
                                  giesbert
                                  wrote on last edited by
                                  #16

                                  [quote author="Volker" date="1301910295"]But once YOUR TestPage is instantiated, it would instantiate another TestPage within the first one!

                                  This IS recursion, believe it or not.

                                  The compiler is always rightâ„¢.[/quote]

                                  That's exactly what I wanted to say. And it happens the same way with my example C++ code (you could also use a pointer and a c'tor that creates it):

                                  @
                                  class Foo {
                                  public:
                                  Foo() {
                                  member = new Foo;
                                  }
                                  Foo* member;
                                  };
                                  @

                                  This also crashes if you create the first Foo, not before! It's exactly the same.

                                  Nokia Certified Qt Specialist.
                                  Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                                  1 Reply Last reply
                                  0
                                  • T Offline
                                    T Offline
                                    Tipiak
                                    wrote on last edited by
                                    #17

                                    Your example is wrong.
                                    The doc says it is load when it is requested.
                                    so i see it more like this, in c++:
                                    @
                                    struct Foo
                                    {
                                    Foo() : m_foo(0)
                                    {
                                    }

                                    Foo *m_foo;
                                    

                                    };

                                    int main()
                                    {
                                    Foo foo;
                                    foo.m_foo = new Foo;
                                    return 0;
                                    }
                                    @

                                    And actually it is not accurately true. Here we said our component has a member of its type. But that is not necessarily the case. As I figure it, a Component is something like a type in C++, so, an inline component is more like a typedef or a inner class.

                                    @
                                    struct Foo
                                    {
                                    Foo() : m_foo(0)
                                    {
                                    }
                                    Foo *createBar() {
                                    struct Bar : public Foo
                                    {
                                    Bar *m_bar;
                                    };
                                    //do stuff, like init variables....
                                    return new Bar;
                                    }
                                    Foo *m_foo;
                                    };

                                    int main()
                                    {
                                    Foo foo;
                                    foo.m_foo = new Foo;
                                    Foo *foobar = foo.createBar();
                                    foobar = new Foo;

                                    return 0;
                                    

                                    }
                                    @

                                    .signature

                                    1 Reply Last reply
                                    0
                                    • G Offline
                                      G Offline
                                      giesbert
                                      wrote on last edited by
                                      #18

                                      A type is not the same as a typedef!
                                      A class is a type, an int is a type.
                                      a typedef is only a name.

                                      and if you have the following:

                                      TestPage.qml

                                      @
                                      item {
                                      id: item1
                                      Component {
                                      id: inneritem
                                      Rectangle {
                                      }
                                      }
                                      }
                                      @

                                      If you create the component TestPage, the rectangle is created. The Rectangle is a client of the component. If your component contains another component, it is created when the component is created. If you contain yourself, you create yourself recursively!

                                      And back to my first example (which the compiler would reject!):

                                      @
                                      class Foo
                                      {
                                      Foo member;
                                      }
                                      @

                                      a type containing itself! Same as

                                      Foo.qml
                                      @
                                      item {
                                      Component {
                                      id: inneritem
                                      Foo {
                                      }
                                      }
                                      }
                                      @

                                      Nokia Certified Qt Specialist.
                                      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                                      1 Reply Last reply
                                      0
                                      • T Offline
                                        T Offline
                                        Tipiak
                                        wrote on last edited by
                                        #19

                                        [quote author="Gerolf" date="1301917914"]A type is not the same as a typedef!
                                        [/quote]
                                        uh? Once defined, the type defined by the typedef is a type, or missed a something obvious for years.
                                        [quote author="Gerolf" date="1301917914"]
                                        A class is a type, an int is a type.
                                        [/quote]
                                        Agreed.
                                        [quote author="Gerolf" date="1301917914"]
                                        a typedef is only a name.
                                        [/quote]
                                        A typedef is a declaration, like a function prototype, a class/struct. Its purpose is to declarate a type based on another type (type aliasing) or a composite type in C.
                                        [quote author="Gerolf" date="1301917914"]
                                        and if you have the following:

                                        TestPage.qml

                                        @
                                        item {
                                        id: item1
                                        Component {
                                        id: inneritem
                                        Rectangle {
                                        }
                                        }
                                        }
                                        @

                                        If you create the component TestPage, the rectangle is created.
                                        [/quote]
                                        Again, that's not what the doc tells me! Or we have not the same defnition of "created".
                                        Mine says it's when the rectangle is created, whit his children, initialized and Component.onCompleted called. It's not the case until you load your component with a loader.
                                        [quote author="Gerolf" date="1301917914"]
                                        The Rectangle is a client of the component. If your component contains another component, it is created when the component is created. If you contain yourself, you create yourself recursively!
                                        [/quote]
                                        Again and again, an inline Component is (should be?) just a definition in a definition. Not a creation/instantiation.
                                        [quote author="Gerolf" date="1301917914"]
                                        And back to my first example (which the compiler would reject!):

                                        @
                                        class Foo
                                        {
                                        Foo member;
                                        }
                                        @

                                        a type containing itself! Same as

                                        Foo.qml
                                        @
                                        item {
                                        Component {
                                        id: inneritem
                                        Foo {
                                        }
                                        }
                                        }
                                        @[/quote]
                                        Yeah that's obviously wrong in c++, I fully understand that. But this it is not the translation i make of a Component. Mine is juste above and i'm pretty sure it's what the doc says and what semantically should happen in qml.

                                        .signature

                                        1 Reply Last reply
                                        0
                                        • G Offline
                                          G Offline
                                          giesbert
                                          wrote on last edited by
                                          #20

                                          [quote author="Tipiak" date="1301919705"][quote author="Gerolf" date="1301917914"]A type is not the same as a typedef!
                                          [/quote]
                                          uh? Once defined, the type defined by the typedef is a type, or missed a something obvious for years.
                                          [/quote]

                                          A typedef is just another name for an existing type or for example a template. So typedef itself does not create a real type, it just gives another name for a type, more like a reference does not create an object, it#s just another name :-)

                                          otherwise, such things would not work:
                                          @
                                          class A
                                          {
                                          puiblic:
                                          explicit A();
                                          explicit A(const A&);
                                          }

                                          typedef B A;

                                          A myObj;
                                          B myObj2;
                                          A myObj3(myObj2);
                                          @

                                          [quote author="Tipiak" date="1301919705"]
                                          Again, that's not what the doc tells me! Or we have not the same defnition of "created".
                                          Mine says it's when the rectangle is created, whit his children, initialized and Component.onCompleted called. It's not the case until you load your component with a loader.
                                          [/quote]

                                          TestPage.qml

                                          @
                                          item {
                                          id: item1
                                          Component {
                                          id: inneritem
                                          Rectangle {
                                          color: "red"
                                          width: 10
                                          height: 10
                                          }
                                          TestPage{
                                          }
                                          }
                                          }
                                          @

                                          If you instantiate the type TestPage, all inner objects are created, right? including the height, width, etc. So if Rectangle is instantiated, also TestPage sub object will be created. This is the recursion!

                                          Nokia Certified Qt Specialist.
                                          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                                          1 Reply Last reply
                                          0

                                          • Login

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