qtqmlcomponentsloaderreusability

Qt QML: in-file definition of reusable objects


I have a Qml component that is reasonably large so that I want to make it a reusable component but it is too small/non-generic such that I want to avoid creating its own .qml file. It seems like Components are the right method to define reusable objects in the same file, but when I do that I don't know how to access and change properties of the contained objects.

More specifically, imagine having an in-file definition like this

Component {
id: myReusableComponent
// This cannot be set because component does not allow properties
// (Would work fine in a separate file myReusableComponent.qml)
// property alias string innerText: innerText.text
Rectangle {
    id: rect
    width: 200
    height: 200
    color: "red"
    Text {
        id: innerText
        text: "Want to set text later"
    }
}

How can I reuse this component later, while changing some properties of it? I know the following is not valid syntax, but I want to use it similarly to this:

Loader {
id: hello
sourceComponent: myReusableComponent
item.innerText: "Hello" }

Text { text: "Some other stuff in between" }

Loader {
id: world
sourceComponent: myReusableComponent
item.anchors.left: hello.right
item.rect.width: 100
item.rect.color: "blue"
item.innerText: "World" }

Loader {
id: excl
sourceComponent: myReusableComponent
item.rect.color: "green"
item.innerText: "!!!" }
etc...

Any ideas? Or is there a fundamentally different way of doing this?
What I essentially want is reusability of QML objects that are defined in place while still being able to change the properties of them.

This seems to be related but does not solve the problem of creating multiple objects. Repeaters seem to be useful but don't give me the flexibility I want.


NOTE: I will add some remarks about the answers here since they might get overlooked in the comments. I like all three answers from Blabbouze, derM and ddriver! I accepted Blabbouze's answer because it provides a concrete solution that is closest to what I was looking for. However, I also didn't know about the overhead of Loaders and might consider using a different approach after reading derM's answer. Finally, dynamic object creation as suggested by ddriver is not exactly what I was looking for but might be useful for others. Thanks everyone!


Solution

  • I think you are looking for onLoaded() signal. It is emitted when the Loader have successfully created the Component.

    You can then access your loaded type properties with item.

    import QtQuick 2.7
    import QtQuick.Controls 2.0
    
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
    
        Component {
            id: myReusableComponent
            Rectangle {
                id: rect
                property alias innerText: innerText.text
    
                width: 200
                height: 200
                color: "red"
                Text {
                    id: innerText
                    text: "Want to set text later"
                }
            }
        }
    
    
        Loader {
            id: hello
            sourceComponent: myReusableComponent
            onLoaded: {
                item.innerText = "hello"
            }
        }
    
        Loader {
            id: world
            sourceComponent: myReusableComponent
            anchors.left: hello.right
            onLoaded: {
                item.width =  100
                item.color =  "blue"
                item.innerText =  "World"
            }
        }
    }