Reputation: 497
I wonder if there is a way to select an already created QML object with a specific id
or objectName
in a javascript function by var (the var is a string parameter corresponding to the QML object id or name).
Eg:
// main.qml
ApplicationWindow {
RoundButton {
id: btn1
}
RoundButton {
id: btn2
}
RoundButton {
id: btn3
}
// ...
function foo(qmlObjectNameOrId) {
qmlObjectNameOrId.text = "qmlObjectNameOrId is already in the document and has a property text that I want to set";
// Qt.findQmlObject(id) would have been great !
}
}
The Qt.createQmlObject
is not a solution as I want to use already created QML objects.
In C++, the way to achieve this is to use QQmlApplicationEngine
object and then use the QML root object to perform the selection by QML object name :
int main(int argc, char *argv[])
{
QQmlApplicationEngine engine;
QString objectName = someFunction();
QObject* qmlObject = engine.rootObjects()[0]->findChild<QObject*>(objectName);
// use your qmlObject ...
}
The javascript function would be called in C++ with QMetaObject::invokeMethod(appWindow, "foo", Q_ARG(QVariant, "bar"));
Thanks
[EDIT 1] Attempt to Roman Sverdlov answer:
ApplicationWindow {
id: appWindow
objectName: "appWindow"
// ...
Pane {
id: buttonsContainer
objectName: "buttonsContainer"
property string disposition : "circular_1"
property int btnWidth : 130
property int btnHeight : 130
property int btnIconWidth : 40
property int btnIconHeight : 40
property int btnRadius : btnWidth / 2
property int btnMargin : 40
property int btnZ : 4
property int btnPressedBackground: Material.Purple
anchors.right: parent.right
anchors.left: parent.left
anchors.top: instructionContainer.bottom
anchors.bottom: parent.bottom
visible: false
Image {
id: background
height: buttonsContainer.height - 100
x: (buttonsContainer.width - width) / 2
y: (buttonsContainer.height - height) / 2
source: "qrc:///images/circle_background.png"
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
fillMode: Image.PreserveAspectFit
}
Rectangle {
id: topLeft
color: Material.color(Material.Red)
x: 0
z: 1
height: parent.height / 2
width: parent.width / 2
}
Rectangle {
id: topRight
color: Material.color(Material.Green)
x: parent.width / 2
z: 1
anchors.top: parent.top
height: parent.height / 2
width: parent.width / 2
}
Label {
id: backgroundTextTop
text: "MONTER"
font.pixelSize: 40
x: (parent.width - width) / 2
y: (parent.height - height) / 2 - 50
z: 2
}
Rectangle {
id: bottomLeft
color: Material.color(Material.Green)
x: 0
z: 1
anchors.bottom: parent.bottom
height: parent.height / 2
width: parent.width / 2
}
Rectangle {
id: bottomRight
color: Material.color(Material.Red)
x: parent.width / 2
z: 1
anchors.bottom: parent.bottom
height: parent.height / 2
width: parent.width / 2
}
Label {
id: backgroundTextBottom
text: "PLONGER"
font.pixelSize: 40
x: (parent.width - width) / 2
y: (parent.height - height) / 2 + 200
z: 2
}
RoundButton {
id: btnB1MB
objectName: "btnB1MB"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B1MB);
}
onReleased: {
TestsRun.releaseButton(Buttons.B1MB);
}
}
RoundButton {
id: btnB4MT
objectName: "btnB4MT"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B4MT);
}
onReleased: {
TestsRun.releaseButton(Buttons.B4MT);
}
}
RoundButton {
id: btnB3MB
objectName: "btnB3MB"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B3MB);
}
onReleased: {
TestsRun.releaseButton(Buttons.B3MB);
}
}
RoundButton {
id: btnB4PB
objectName: "btnB4PB"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B4PB);
}
onReleased: {
TestsRun.releaseButton(Buttons.B4PB);
}
}
RoundButton {
id: btnB2MT
objectName: "btnB2MT"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B2MT);
}
onReleased: {
TestsRun.releaseButton(Buttons.B2MT);
}
}
RoundButton {
id: btnB1PT
objectName: "btnB1PT"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B1PT);
}
onReleased: {
TestsRun.releaseButton(Buttons.B1PT);
}
}
RoundButton {
id: btnB2PB
objectName: "btnB2PB"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B2PB);
}
onReleased: {
TestsRun.releaseButton(Buttons.B2PB);
}
}
RoundButton {
id: btnB3PT
objectName: "btnB3PT"
width: buttonsContainer.btnWidth
height: buttonsContainer.btnHeight
radius: buttonsContainer.btnRadius
z: buttonsContainer.btnZ
display: AbstractButton.TextUnderIcon
onPressed: {
TestsRun.pressButton(Buttons.B3PT);
}
onReleased: {
TestsRun.releaseButton(Buttons.B3PT);
}
}
Component.onCompleted: {
setButtonsPosition(buttonsContainer.disposition);
}
}
/**
* Get a QML element by objectName property
*
* @todo Not working
*
* @param {String} objectName - The QML object name to get
*/
function getQmlObjectByName(objectName) {
console.log("buttonsContainer.children.length", buttonsContainer.children.length);
return getQmlObjectByNameRecursive(buttonsContainer, objectName)
}
/**
* Get a QML element by objectName property
*
* @todo Not working
*
* @param {Object} object - The QML object to find the QML element in
* @param {String} objectName - The QML object name to get
*/
function getQmlObjectByNameRecursive(object, objectName) {
for (let child in object.children) {
console.log(object.children[child].objectName);
if (object.children[child].objectName === objectName) {
console.log('found');
return object.children[child];
}
if (typeof object.children[child].children !== 'undefined') {
console.log('children', object.children[child]);
return getQmlObjectByNameRecursive(object.children[child], objectName);
}
}
}
output
qml: buttonsContainer.children.length 2
qml: Pane
qml: children QQuickContentItem(0x55c4e2a145d0, "Pane")
qml:
qml: children QQuickImage(0x55c4e2a1cc80)
qml: undefined
Upvotes: 6
Views: 1930
Reputation: 497
Problem solved by iterating over a QML container which I want to find the QML object by objectName property in.
Thanks to Roman Sverdlov, the "DOM traversal" is done with the contentChildren
property and not children
property.
/**
* Get a QML element by objectName property in buttonsContainer container
*
* @param {String} objectName - The QML object name to get
*/
function getQmlObjectByName(objectName) {
for (let child in buttonsContainer.contentChildren) {
if (buttonsContainer.contentChildren[child].objectName === objectName) {
return buttonsContainer.contentChildren[child];
}
}
}
Upvotes: 1
Reputation: 93
if you have objectName
property set for your objects then you can use something like
ApplicationWindow {
id: appWin
RoundButton {
id: btn1
objectName: "btn1"
}
RoundButton {
id: btn2
objectName: "btn2"
}
// ...
function foo(objectName) {
for(var child in appWin.children) {
if(appWin.children[child].objectName === objectName) {
appWin.children[child].text = "qmlObjectNameOrId is already in the document and has a property text that I want to set";
break
}
}
}
}
Of course it looks ugly, but if you need it a lot...
Upvotes: 1