Solved Use a custom item as a children declared as a property (like delegate in views)
-
I'm trying to create an object where you can declare a custom item that will be inserted in my custom object. But I don't know how to use this delegate later in my code.
Example:// MyObject.qml Row { property var customItem ItemBefore { } // This where I don't know how to use the custom item customItem { // That would be even better if I could set properties // that are used by the item (width, height, ...) // like with a regular QML object someProperties: true } ItemAfter { } } // Main.qml Item { MyObject { customItem: Rectangle { color: "#FF0000" } } MyObject { customItem: Rectangle { color: "#00FF00" } } MyObject { customItem: Rectangle { color: "#0000FF" } } }
The behavior I'm looking for is similar to the one used by
ListView
andGridView
with thedelegate
property.
Can anyone help me ?
MoaMoaK -
The easiest way I can think to do this in pure QML is use a
Repeater
instead of your custom object. It takes a delegate but does not impose any particular layout. You can let the items position themselves (e.g. using x/y properties in the delegate based on the model) or you can control their layout yourself by using theitemAdded
signal and adjusting properties of theitem
there.But assuming that does not meet your needs, and since it does not answer your question, I would wrap your delegate in a
Component
so that you can easily instantiate it usingcreateObject()
:main.qml
import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible:true; width:640; height:480; title:"Replicator" Replicator { copies: 15 Component { Rectangle { width:200; height:100 color:Qt.rgba(255,0,0,0.2); border.color:'red' property alias label: t.text Text { id:t; anchors.centerIn:parent } } } } }
Replicator.qml
import QtQuick 2.0 Item { id: root anchors.fill: parent property int copies: 5 default property var template Component.onCompleted: { for (var i=copies;i--;) { var props = { label: "I'm item #"+i, x: Math.random()*root.width/2, y: Math.random()*root.height/2 }; template.createObject(root, props); } } }
This produces a result like:
In the example above I've used the
default
keyword to allow your delegate without a label. This is purely optional.There may be a way to do this without a
Component
, but I don't know what it is. The page on Dynamic QML Object Creation says:There are two ways to create objects dynamically from JavaScript. You can either call
Qt.createComponent()
to dynamically create a Component object, or useQt.createQmlObject()
to create an object from a string of QML.You don't have a string of QML, and so you must use a component.
A true delegate object like ListView and Repeater accept would require some way to derive a component from an instance, and that does not appear to me to be possible in pure QML.
-
@MoaMoaK Using a Loader should perfectly do want you want to achieve:
// MyObject.qml Row { property alias customItem: loader.sourceComponent ItemBefore { } Loader { id: loader // Just a bunch of custom properties property int widthOfCustomItem: 100 property int heightOfCustomItem: 100 } ItemAfter { } } // Main.qml Item { MyObject { customItem: Rectangle { color: "#FF0000" // You can use all properties of the Loader inside your customItem width: widthOfCustomItem height: heightOfCustomItem } } MyObject { customItem: Rectangle { color: "#00FF00" } } MyObject { customItem: Rectangle { color: "#0000FF" } } }
-
@DuBu Sorry I'm a bit late, but really using Loader was THE solution I wanted, thx a lot.
It works perfectly.