Pushing to StackView with property bindings



  • Hello all,

    I've got a problem when trying to push a component to a StackView and I hope someone could clarify this.

    In a QML slot I push a custom component to a StackView like this:

    var deviceList = Qt.createComponent("DeviceGroups.qml");
    if(deviceList.status === Component.Ready) {
        stack.push(deviceList, { "model": modelManager.locationContent } );
    }
    

    DeviceGroups.qml is a customized ListView and the above code works as expected, hence the model is properly set. However it seems that no property bindings are created when setting the model like this. The ListView does not get updated when the model does. I confirmed that the relevant signal is being emitted and received in QML but the ListView doesn't care. To confirm this I tried the same with a simple text element which I update via a QML Timer like this:

    Text {
         id: testText
         text: "This is a test"
    }
    Timer {
         interval: 5000
         onTriggered: testText.text = testText.text + "."
         running: true
         repeat: true
    }
    
    [...]
    
    onClicked: {
        var deviceList = Qt.createComponent("Test.qml");
        if(deviceList.status === Component.Ready) {
            stack.push(deviceList, { "text": testText.text } );
        }
    }
    

    Test.qml is a simple Text item so the resulting view should be updated every time the timer triggers, or am I missing something?

    Thanks for any help
    Tobi


  • Moderators

    Hi! I didn't fully get what you're doing there but are you aware of the fact that you're only creating a component without actually instantiating an object from it? I guess your code should more look like this:

    var component = Qt.createComponent("Button.qml"); // only a component so far
    if (component.status == Component.Ready) {
      var button = component.createObject(container); // now we have an instance
      button.color = "red";
    }
    


  • @Wieland said:

    Hi! I didn't fully get what you're doing there but are you aware of the fact that you're only creating a component without actually instantiating an object from it?

    Thanks for the tip. But is there any difference in pushing a component to the StackView or pushing an actual instance?

    To elaborate further on my problem, if I change your example a bit it might get clearer:

    var component = Qt.createComponent("Button.qml"); // only a component so far
    if (component.status == Component.Ready) {
      var button = component.createObject(container); // now we have an instance
      button.color = somePropertyThatChangesOverTime;
      stack.push(button);
    }
    

    My problem with this is that the color of the button that is pushed onto the StackView would not get updated.
    Is this a bug or do I have to create the property binding myself (if yes, how) ?

    Thanks in advance!


  • Moderators

    @MrBolton said:

    But is there any difference in pushing a component to the StackView or pushing an actual instance?

    A "component" is only like a class definition in C++. See Creating a Component Dynamically.

    @MrBolton said:

    My problem with this is that the color of the button that is pushed onto the StackView would not get updated.
    Is this a bug or do I have to create the property binding myself (if yes, how) ?

    It's not a bug, and yes, here you have to create the binding yourself. That's because button.color = someThingThatChanges is just a Javascript assignment. It only once copies the current value of someThingThatChanges to button.color at exactly this point of execution. If you want to create a binding from Javascript code you can do it like this:

    button.color = Qt.binding(function() { return someThingThatChanges});
    


  • StackView::push() accepts Items, Components, and URLs. If you want to push a QML file, the most straight-forward way is to pass the URL and let StackView handle the rest.

    Passing properties to StackView::push() works identically with Component::createObject(). If you want to create a binding, you'll need to use Qt.binding().

    stack.push(Qt.resolvedUrl("Button.qml"), {color: Qt.binding(function() { return foo.bar })})
    

    We'll add a note about the property bindings to the docs.


  • Moderators

    @jpnurmi Thx for clarifying this! :)



  • Thank you all! As soon as I created the binding, it works like a charm!
    And thanks to the explanation on component creation, it's now much less code! :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.