Reputation: 4052
It's very weird because I use almost the same pattern in another QML file and it works correctly! I'm sure I'm not reassigning value anywhere (the only thing I know that can make property static)! I have something like this (it's a simplified example and probably works as expected):
Item {
property bool isExpanded: false
MouseArea {
anchors.fill: parent
onClicked: {
isExpanded = !isExpanded
console.log(isExpanded)
console.log(myId.visible)
}
}
MyCustomItem {
id: myId
visible: isExpanded
// other stuff
}
}
IsExpanded
changes after I click but Item
visibility always stays the same! And I have many other properties for my item (for example height: isExpanded ? someval : 0
) which doesn't change too! It sort of works if I always change everything manually but whats the point then? And in another QML I use a similar pattern and there it works!
BUT! If I put, for example onDoubleClicked
/another button press:
myId.visible = Qt.binding(function() {return isExpanded})
it works as it should! So, for some unknown reason it doesn't 'bind' them when it should in regular property declaration (visible: isExpanded
).
So the question is, do I really need to explicitly tell Qt to bind property to make it work?
Edit: To make clear: I'm certain I don't reassign visible property anywhere. I doble checked it. And though qml size is only about 100 of lines I used ctrl+f to find any mention of visible and found none except already mentioned. If there is more reliable way to tell what's from/ check for possible reassignments somewhere or something, please tell.
Upvotes: 1
Views: 3946
Reputation: 4052
I found the issue! Very unobvious (haven't found documented anywhere) and it fails silently.
The problem is that MyCustomItem
contained a property with the same name of outer booleal property isExpanded
so in this code:
MyCustomItem {
id: myId
visible: isExpanded
// other stuff
}
isExpanded
is from MyCustomItem
. But without any indication of that. Well, now I know that this could happen and would probably spot it if it happens again but this is really counter-intuitive. What if it wasn't my item but someone else's and I didn't know that it had such property? Qt creator could've at least warned about possible ambiguities.
Upvotes: 1
Reputation: 22346
So the question is, do I really need to explicitly tell Qt to bind property to make it work?
Yes.
When declaring a property, you can use the binding syntax e.g. visible: isExpanded
. But setting a property in imperative code using normal JavaScript syntax (i.e. the assignment operator) will break any existing binding and overwrite the property's value. If you want to explicitly set a property binding in imperative code, use the Qt.binding()
method (docs).
Although your actual problem is due to falling victim to QML's scoping rules. Your MyCustomItem
type has an isExpanded
property, so when you declare:
MyCustomItem {
id: myId
visible: isExpanded
// other stuff
}
You're actually binding visible
to MyCustomItem::isExpanded
. So to fix just be explicit as to which isExpanded
you are referring to:
Item {
id: base
property bool isExpanded: false
MouseArea {
anchors.fill: parent
onClicked: {
isExpanded = !isExpanded
console.log(isExpanded)
console.log(myId.visible)
}
}
MyCustomItem {
id: myId
visible: base.isExpanded
// other stuff
}
}
Upvotes: 4