QML connect signal from the main component to the child components

时间:2017-08-04 12:51:27

标签: qml connect signal-handling

I have a Qt application that calls qt_update_values() to the main QML component. I want to send the new values to a specific delegate. How do I connect update_values() from the main component to be received by a specific child component, which is defined in another qml?

I have tried defining Connections in the child, but I am not sure what target I need to define...

In the main.qml i have something similar to this:

...
signal update_values(new_values)

function qt_update_values(newValues){
     update_values(newValues);
}

Repeater {
     id:idRepeater
     model: 3

     Rectangle {
         id:example

         Text{ text: "hello"}
         ...

         AnotherComponent {name: "name", othervariables: "others"}
     }
}
...

Then on AnotherComponent.qml i have:

...
signal update_values_child(new_values)

function onUpdate_values(newValues){
     textid = newValues;
}

Text{ id:textid}
...

1 个答案:

答案 0 :(得分:0)

You don't connect from the parent to the main, but the other way around like this:

...
id: idOfTheParent  // <=== THIS IS IMPORTANT
signal update_values(new_values)

function qt_update_values(newValues){
     update_values(newValues);
}

Repeater {
    id:idRepeater
    model: 3

    Rectangle {
        id:example

        Text{ text: "hello"}
        ...

        AnotherComponent {
            id: idOfAnotherComponent // This ID is only available in the 
                                     // scope of the Component
                                     // that will be instantiated by the
                                     // Repeater, i.e. children of the Rectangle
            name: "name"
            othervariables: "others"
        }
        Connections {
            target: idOfTheParent
            onUpdate_values: idOfAnotherComponent.dosomethingWith(new_values)
        }
    }
}
...

You could also use signal.connect() to add new connections

Repeater {
    model: 10
    delegate: Item { ... }
    onItemAdded: {
        idOfTheParent.update_values.connect(function() { // do what you want })
    }
}

But if it is only broadcasting of a new value, the declarative way would be, to have properties in your delegate, and bind them to the properties that held the changeing values:

...
id: idOfTheParent
property var valueThatWillChange

Repeater {
    model: 10
    delegate: Item {
        property int valueThatShallChangeToo: idOfTheParent.valueThatWillChange
    }
}
...

To have all of it with different signals ofc. is possible:

For the Connections-solution the simplest thing is to call doSomething only if it is the right delegate instance:

// in the delegate
Connections {
    target: idOfTheParent
    onValue1Updated: if (index === 1) doYourStuff()
    onValue2Updated: if (index === 2) doYourStuff()
    onValue...
}

But this is easier with the second method:

id: idOfTheParent
Repeater {
    model: 10
    delegate: SomeItem {
        function doSomething() { console.log(index, 'does something')
    }
    onItemAdded: {
        idOfTheParent['value' + index + 'Updated'].connect(item.doSomething)
    }
    onItemRemoved: {
        idOfTheParent['value' + index + 'Updated'].disconnect(item.doSomething)
    }
}