I'm trying to create a QML object that acts like a wrapper for other objects. Here's my QML file (Container.qml):
Item {
property string label
property Item control
Row {
Label {
text: label
}
// Not sure how to display the control assigned to the control property
}
}
What I would like to do (in my QML that consumes this component) is something like this:
Container {
label: "My Label"
control: Textbox {
text: "My Value"
}
}
When fed that QML the result (in the interface) should be something resembling the output from this QML:
Item {
Row {
Label {
text: "My Label"
}
Textbox {
text: "My Value"
}
}
}
Is this possible? When I try to do this I get "cannot assign object to property" when assigning an Item to the control property. I've searched the Qt forums and Googled this mercilessly, but no success. If anybody knows the answer it would be greatly appreciated.
Thanks
Jack
A property is an attribute of an object that can be assigned a static value or bound to a dynamic expression. A property's value can be read by other objects. Generally it can also be modified by another object, unless a particular QML type has explicitly disallowed this for a specific property.
A component provides a way of defining a new type that we can re-use in other QML files. A QML component is like a black-box and interacts with the outside world through properties, signals and functions and is generally defined in its own QML file. (For more details, see the Component documentation).
There is much better solution:
/* MyObject.qml */
Rectangle {
default property alias data /* name can be any */ : inner_space.data
/* ... You can put other elements here ... */
Item {
id: inner_space
/* ... Params ... */
}
/* ... You can put other elements here ... */
}
And now we can do all we want!
/* main.qml */
Rectangle {
MyObject {
Button {
/* ... */
}
}
}
Thanks to user bobbaluba for suggesting to use the data
property rather than children
.
You can dynamically load items using the Loader element, and then set the 'control' property to be an alias that directly refers to the loader's sourceComponent property.
So your Container.qml could look like this:
Item {
property string label
property alias control : loader.sourceComponent
width: 200; height: 200
Row {
Label { text: label }
Loader { id: loader }
}
}
Now when you assign a graphical item to the 'control' property, it will automatically be displayed by the Loader.
You can create a container for other items using a custom property:
Item
{
id: root
property list<Item> rectList: [
Rectangle
{
parent: root
},
Rectangle
{
parent: root
},
Rectangle
{
parent: root
},
Rectangle
{
parent: root
}
]
}
Note that the parent of the Rectangle Items is set manually so they will be visual children of the container.
You can assess them as a javascript array
for ( var i = 0; i < root.rectList.length; i++ )
{
var rect = root.rectList[i];
rect.visible = true;
}
or
rect.rectList[1].visible = false;
Been using QML for about a month now, no idea really how to do this I'm afraid.
Best plan is to figure out all possible things that the control (Textbox
in your example) could be, create an instance of each component in your row, and set a corresponding state on your Item
. The state would then take care of making the desired component visible or invisible as appropriate.
Edit
Just thought. (Haven't tried this but give it a go!) In your Item
's Component.onCompleted:
handler, try calling control.createObject(rowID)
where rowID
is an id
for your Row
object, (which you want to be the parent of control
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With