Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a "template" with child placeholders in QML?

Tags:

qt

qt-quick

qml

I really like QML. I like how I can define components (comparable to classes) and their properties, and instantiate them from somewhere else (comparable to objects).

I can define, let's say, a button, having some look and feel, and a label text on it. This could be done, for example, using this component definition (Button.qml):

Item {     id: button     property string label      anchors.fill: parent      Rectangle {         anchors.fill: parent         radius: 10         color: "gray"          Text {             anchors.centerIn: parent             font.pixelSize: 20             text: button.label             color: "white"         }     } } 

and instanciated in this main file (main.qml):

Rectangle {     width: 300     height: 200      Button {         anchors.centerIn: parent         anchors.margins: 50         label: "Hello button!"     } } 

But I see the following restriction: I can only define a button template with some properties, not with some placeholder. All children defined in the instance will be direct children, at least per default, and I want to change this behavior.

Let's say I want to place an item (let's say an image, but I don't want to tell the definition of Button that it will be an image) in the button. I imagine something like this:

Item {     id: button     property Item contents   <-- the client can set the placeholder content here      anchors.fill: parent      Rectangle {         anchors.fill: parent         radius: 10         color: "gray"          Item {             id: placeholder     <-- where the placeholder should be inserted         }     }      Component.onCompleted: {         // move the contents into the placeholder...     } } 

How can I achieve this? I don't know if using Component.onCompleted is the correct way. Note that, however, that in my case the contents will never change afterwards (at least in my current design of the application...).

Also, I want anchoring to work within the placeholder. For example, if I define the contents to be a Text element, being centered in its parent (which will first be the template itself). Then my code moves this Text instance into the placeholder and the parent anchors should then be those of the placeholder item, not the template item.

like image 252
leemes Avatar asked Sep 18 '12 12:09

leemes


1 Answers

I found a much nicer answer to this question, suggested in a presentation of the Qt Developer Days 2011 "Qt Quick Best Practices and Design Patterns".

They use default property alias ... to alias the child items to any property of any item. If you don't want to alias the children but give the alias property a name, just remove default. (Literal children are per QML definition the value of the default property.)

Item {     id: button     default property alias contents: placeholder.children      anchors.fill: parent      Rectangle {         anchors.fill: parent         radius: 10         color: "gray"          Item {             id: placeholder     <-- where the placeholder should be inserted         }     } } 
like image 166
leemes Avatar answered Sep 21 '22 14:09

leemes