Change property of items in component from outside



  • hi guys,

    question: i want change a item in a component from outside but i cant find a solutuion for that.
    example:

    main.qml
    @
    Repeater {
    model:8
    component1 {
    ...
    }
    }
    @

    component1.qml

    @
    component2 {
    id: root
    property int textWidth: 25
    property int displayedHeight: heightInMeter

    Text {
    x: 0
    y: - font.pixelSize * 0.5
    width: root.textWidth
    horizontalAlignment: Text.AlignRight

    text: displayedHeight + " m"
    color: config.scaleItem_TextColor
    }
    @

    component2.qml

    @
    Item {
    id: root

    property QtObject config
    property double heightInMeter

    x: Math.round(config.leftInMeter * config.xPixelPerMeter)
    y: Math.round(heightInMeter * config.yPixelPerMeter)

    Rectangle {
    anchors {
    left: parent.left
    leftMargin: 30
    }

    height: 1
    width: config.widthInMeter * config.xPixelPerMeter - anchors.leftMargin

    color: config.scaleItem_LineColor
    }

    }
    @

    Now I want to change the width of the rectangle in component2 from my main.qml. How can I access this variable?
    My actual solution for that is, to give each component some properties what I can access from outside. But i'm not happy with this, because every time I have to edit the component if I want to change an variable from outside.
    Any other ideas to solve that problem?

    Regards


  • Moderators

    Hi,

    You can keep a global property in main.qml. Bind this property to the Component's Width property. So whenever that global property changes the Component's Width will also change. Ofcourse it will also affect other Components since you are using a Repeater but for that you can keep another property in main.qml which will contain the index of the Component, so that you can check it in individual Component whether its Width should change.



  • That is the way I did it. But every time I decide to change an additional property I have to change the components. This i don't want. If there is no other possiblity I will do so. But i hope that QT has a feature what I can use to change the property directly.


  • Moderators

    AFAIK, to change the property directly you will need to find the exact Component which you have loaded through Repeater and it would quite cumbersome.



  • Can you explain it? I mean forget the Repeater, How to change the property in the component from outside?


  • Moderators

    Well it depends upon how you instantiate the Component
    For eg if you use Loader to load a Component, you can use "Loader.item":http://doc.qt.io/qt-5/qml-qtquick-loader.html#item-prop to get access to it.
    Or if you use createComponent and createObject you can access the properties directly.
    @
    var component = Qt.createComponent("Button.qml");
    if (component.status == Component.Ready) {
    var obj = component.createObject(parent, {"x": 100, "y": 100});
    console.log(obj.x,obj.y)
    }
    @

    For ref. check "here":http://doc.qt.io/qt-5/qml-qtqml-component.html#createObject-method.



  • I didn't instance the components over a function i just use
    @
    import "components/"
    @

    I don't want change just the compnent property like position width etc.
    my component has more like one item (see the example above, componet2.qml)
    and now i want access one of this items and change the properties.

    I checked the loader function and the qt.createComponent but it looks like that they don't fit my needs. Or I'm blind to see it.
    At the moment I decided to write the components as a Item in the Repeater and change the property manual. See the example. But I'm not happy with that.
    (Identical with the first example just change the width of the rectangle to width: 30)
    @
    Repeater {
    model:12

    Item {
     property int textWidth: 25
     property int displayedHeight: heightInMeter
     //property QtObject config
     property double heightInMeter: ((-2) + ( index * 2 ))
    
     x: Math.round(root.config.leftInMeter * config.xPixelPerMeter)
     y: -Math.round(heightInMeter * config.yPixelPerMeter)
    
     Text {
      x: 0
      y: - font.pixelSize * 0.5
      width: parent.textWidth
      horizontalAlignment: Text.AlignRight
      text: displayedHeight + " m"
      color: root.config.scaleItem_TextColor
     }
     Rectangle {
      anchors {
       left: parent.left
       leftMargin: 30
      }
      height: 1
      width: 30
      color: root.config.scaleItem_LineColor
     }
    }
    

    }
    @


  • Moderators

    Well now since we have fallen back to Repeater again, consider the following example similar to yours:
    @
    import QtQuick 2.4

    Item {
    id: item
    width: 200
    height: 400

    Repeater {
        id: repeater
        model: 10
        Rectangle {
            x: 0
            y: index*40
            color: "lightgray"
            border.color: "gray"
            width: 200
            height: 40
            Text {
                objectName: "obj"+index
                anchors.centerIn: parent
                text: "Text" + index
            }
        }
    }
    
    MouseArea {
        anchors.fill: parent
        onClicked: {
            for(var a =0; a< item.children.length; a++)
                if(typeof item.children[a].children[0] !== "undefined")
                if(item.children[a].children[0].objectName==="obj3") {
                    item.children[a].children[0].text = "Found You"
                }
        }
    }
    

    }
    @

    As I said earlier to get access to Item in a Repeater you will need to find the exact Item (in this case Text element with objectName obj3), and then you can access its properties. But it requires iterating through the objects hierarchy.
    Another way as we discussed at the start of the post was to keep the global property and binding to it.



  • Nice way what you describe. Not so useful in that case but an alternative for other problems.
    Thanks for help


  • Moderators

    That's fine. But I think binding to to global property would be the best way. Anyway if you find any other way please post it so that others would too benefit from it.


Log in to reply
 

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