I'm creating a custom QML component (a specialization of ListView
that allows multiple selection). I'd like to provide attached properties to objects provided to my component. I see how to create attached properties using C++. However, I cannot find information on adding custom properties in pure QML. Is this possible using QML?
Attached Properties and Attached Signal Handlers In particular, they allow objects to access properties or signals that are specifically relevant to the individual object. A QML type implementation may choose to create an attaching type in C++ with particular properties and signals.
Define the function in your root-node ( ApplicationWindow ). This will be the last place, QML will look for a name, before it resorts to the C++ -context properties. See here to find out, how the names of variables and functions are resolved in QML.
Is this possible using QML?
No.
There is an alternative, easy and clean way to this in QML - just use an adapter object that implements the desired properties. Then instead of attaching just nest into the adapter - use it as as a parent / container. You can also nest objects into the adapter, getting another C++ exclusive - grouped properties. A possible way to minimize the overhead of this is to use JS objects and properties, with a downside - no change notifications, which you can somewhat mitigate by emitting manually.
An example:
// Adapter.qml - interface with attached properties
Item {
id: adapter
property int customInt : Math.random() * 1000
property var group : {"a" : Math.random(), "b" : Math.random() }
default property Component delegate
width: childrenRect.width
height: childrenRect.height
Component.onCompleted: delegate.createObject(adapter)
}
// usage
ListView {
width: 100
height: 300
model: 5
delegate: Adapter {
Row {
spacing: 10
Text { text: index }
Text { text: customInt }
Text { text: group.a }
Text { text: group.a }
}
}
}
It is fairly painless and convenient compared to some other QML workarounds. You don't even have to do parent.parent.customInt
- the properties are directly accessible as if they are attached, this works because of dynamic scoping. The default property
allows to avoid setting the inner delegate as a property you just nest the delegate you want directly in the adapter.
In many cases those acrobatics are overkill, you can just wrap in place:
ListView {
width: 100
height: 300
model: 5
delegate: Item {
width: childrenRect.width
height: childrenRect.height
property string custom1: "another"
property string custom2: "set of"
property string custom3: "properties"
Row {
spacing: 10
Text { text: index }
Text { text: custom1 }
Text { text: custom2 }
Text { text: custom3 }
}
}
}
The only key part really is the binding for the size of the adapter object so that the view can properly layout the objects. I routinely use a Wrap
element which essentially does the same but is implemented in C++, which is much more efficient than a QML binding.
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