Looping non-visible object creation
-
Hey All,
This is my 1st go with QMl and it is fun so far. My app would benefit greatly from the ability to create and or configure objects in loops. The base classes I am working with are blackboxed and I can not see the source. For the most part I am assuming they are plain objects that do not inherit from Item. The items I would like to put in loops or repeaters are below.ButtonScriptAdapter {}
WiresGroup {}
Wire {}I have tried all sorts of implementations with Repeater, but I haven't had any luck just yet. Using JS function calls initiated from Component.onCompleted has not produced any results.
Currently I think the best way to do this might be to use a repeater to define the object, then go back in JS, get a handle to each item and configure its various parameters.
Any help with this would be great as there is a lot of redundant code I would like to chop out of my app.
ButtonScriptAdapter { name: "PadFX0"; color: colorHandler(0); brightness: lightHandler(0); ... } ButtonScriptAdapter { name: "PadFX1"; color: colorHandler(1); brightness: lightHandler(1); ... } ButtonScriptAdapter { name: "PadFX2"; color: colorHandler(2); brightness: lightHandler(2); ... } ButtonScriptAdapter { name: "PadFX3"; color: colorHandler(3); brightness: lightHandler(3); ... } ButtonScriptAdapter { name: "PadFX4"; color: colorHandler(4); brightness: lightHandler(4); ... } ButtonScriptAdapter { name: "PadFX5"; color: colorHandler(5); brightness: lightHandler(5); ... } ButtonScriptAdapter { name: "PadFX6"; color: colorHandler(6); brightness: lightHandler(6); ... } ButtonScriptAdapter { name: "PadFX7"; color: colorHandler(7); brightness: lightHandler(7); ... }
Another spot for loops...
WiresGroup { id: wireGroup1 enabled: slotPadsFX.value == 1 Wire { from: "%surface%.pads.1"; to: "PadFX0" } Wire { from: "%surface%.pads.2"; to: "PadFX1" } Wire { from: "%surface%.pads.3"; to: "PadFX2" } Wire { from: "%surface%.pads.4"; to: "PadFX3" } Wire { from: "%surface%.pads.5"; to: "PadFX4" } Wire { from: "%surface%.pads.6"; to: "PadFX5" } Wire { from: "%surface%.pads.7"; to: "PadFX6" } Wire { from: "%surface%.pads.8"; to: "PadFX7" } }
I could invision one loop that declares and configures the ButtonScriptAdapter and then adds it to the wireGroup1.
Thanks for the help
-
@Phando said in Looping non-visible object creation:
Hey All,
This is my 1st go with QMl and it is fun so far. My app would benefit greatly from the ability to create and or configure objects in loops. The base classes I am working with are blackboxed and I can not see the source. For the most part I am assuming they are plain objects that do not inherit from Item. The items I would like to put in loops or repeaters are below.ButtonScriptAdapter {}
WiresGroup {}
Wire {}I have tried all sorts of implementations with Repeater, but I haven't had any luck just yet.
It's true, sadly, that Repeater's delegates must be Item-based. :-(
The easiest solution I can think of is to wrap the non-Item in an Item. The wrapper can be 0x0 and have nothing to draw, so overhead won't be that bad.
Repeater { model: theModel delegate: Item { id: wrapper NonItem { prop: wrapper.modelData } } }
Using JS function calls initiated from Component.onCompleted has not produced any results.
If you want to go into the details, post some source. I'm happier with the imperative javascript code in QML kept to a minimum.
-
@jeremy_k said in Looping non-visible object creation:
id: wrapper
NonItem {
prop: wrapper.modelData
}@jeremy_k Thank you for the response! I was just going down the road of wrapping my objects in Items.
How do I reference the repeater index inside the delegate?Repeater { id:rep model: 2 delegate: Item { id: wrapper ButtonScriptAdapter { name: "PadFX" + rep.index color: colorHandler(rep.index) brightness: lightHandler(wrapper.index) onPress: pressHandler(index) onRelease: releaseHander(index) } } } // index // rep.index // wrapper.index // rep.wrapper.index
Once made, how do I go about referencing the NonItems?
mod.wrapper[0].color mod.rep.wrapper[0].color this.wrapper[0].color ...?
-
@Phando said in Looping non-visible object creation:
@jeremy_k said in Looping non-visible object creation:
id: wrapper
NonItem {
prop: wrapper.modelData
}@jeremy_k Thank you for the response! I was just going down the road of wrapping my objects in Items.
How do I reference the repeater index inside the delegate?Repeater { id:rep model: 2 delegate: Item { id: wrapper ButtonScriptAdapter { name: "PadFX" + rep.index color: colorHandler(rep.index) brightness: lightHandler(wrapper.index) onPress: pressHandler(index) onRelease: releaseHander(index) } } } // index // rep.index // wrapper.index
wrapper.index
is the correct scoped naming, althoughindex
will work in some cases. See https://doc.qt.io/qt-6/qml-qtquick-repeater.html#delegate-propYou might also want to represent the list of items as a model, allowing role names to be used instead of lookup functions. https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#qml-data-models provides an overview.
Once made, how do I go about referencing the NonItems?
Column { id: col Repeater { id: repeater model: 5 delegate: Item { property alias adapter: t QtObject { id: t property string text: "index: " + index } } } Button { text: "push me" onClicked: console.log(repeater.itemAt(2).adapter.text, col.children[2].adapter.text) } }
-
@Phando A little more on the actual creation, referencing after fact aside. How do I reference the repeater index inside the delegate?
Repeater { id: repeater model: 1 delegate: Item { property alias adapter: t ButtonScriptAdapter { id: t name: "PadFX0" color: colorHandler(0) brightness: lightHandler(0) onPress: pressHandler(0) onRelease: releaseHander(0) } } }
All that makes sense and thank you for the links. It isn't working for me even when I hard code the values for 'index'. I think the issue is that the objects are not being created as children of the root. From what I have found, the alias modifier changes the scope of the objects. In this case the alias is nested one additional level. Is there a way to add the objects to the root after they are created?
I feel where things are going wrong is later in my code when I have to reference the created objects by their string name.
Wire { from: "%surface%.pads.1"; to: "PadFX0" } //maybe //Wire { from: "%surface%.pads.1"; to: "Wrapper.PadFX0" }
-
@Phando said in Looping non-visible object creation:
@Phando A little more on the actual creation, referencing after fact aside. How do I reference the repeater index inside the delegate?
Use the index property.
For example:
import QtQuick 2.12 import QtQuick.Window 2.12 Window { width: 640 height: 480 Column { anchors.fill: parent Repeater { id: repeater model: 5 delegate: Text { text: index } } } }
All that makes sense and thank you for the links. It isn't working for me even when I hard code the values for 'index'. I think the issue is that the objects are not being created as children of the root.
Repeater delegate instances are children of the Repeater's parent. Take the previous example and change
text: index
totext: parent === repeater.parent
.From what I have found, the alias modifier changes the scope of the objects. In this case the alias is nested one additional level.
I don't understand this. Can you provide an example?
Is there a way to add the objects to the root after they are created?
An object can be imperatively created that is parented to the root, or assigned to a property. It's not a route that I would recommend.
I feel where things are going wrong is later in my code when I have to reference the created objects by their string name.
Wire { from: "%surface%.pads.1"; to: "PadFX0" } //maybe //Wire { from: "%surface%.pads.1"; to: "Wrapper.PadFX0" }
Is using a string to object lookup a requirement of the interface, or is this a result of not knowing how to get a more direct reference to the object?