I'm new to QML and ran into a scope problem while going a button tutorial. I solved it but I don't understand why the code didn't work in the first place:
The following code gives Runtime reference errors when the button is hovered over:
main_broken.qml
import QtQuick 2.0
import QtQuick.Controls 1.1
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Button Tester")
Rectangle {
id: simpleButton
height: 75
width: 150
property color buttonColor: "light blue"
property color onHoverColor: "gold"
property color borderColor: "white"
onButtonClick: {
console.log(buttonLabel.text + " clicked")
}
signal buttonClick()
Text {
id: buttonLabel
anchors.centerIn: parent
text: "button label"
}
MouseArea {
id: buttonMouseArea
anchors.fill: parent
onClicked: buttonClick()
hoverEnabled: true
onEntered: parent.border.color = onHoverColor
onExited: parent.border.color = borderColor
}
color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor
scale: buttonMouseArea.pressed ? 0.99 : 1
}
}
errors:
qrc:///main.qml:37: ReferenceError: onHoverColor is not defined
qrc:///main.qml:38: ReferenceError: borderColor is not defined
qrc:///main.qml:37: ReferenceError: onHoverColor is not defined
qrc:///main.qml:35: ReferenceError: buttonClick is not defined
Solved by just moving the property bindings and signal-slot into the Application window object as follows:
main_fixed.qml
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Button Tester")
property color buttonColor: "light blue"
property color onHoverColor: "gold"
property color borderColor: "white"
onButtonClick: {
console.log(buttonLabel.text + " clicked")
}
signal buttonClick()
//etc
Why is it not possible to leave the property bindings within the Rectangle child of the ApplicationWindow object?
What if you wanted to have properties exclusive only to the rectangle (e.g. colour), but that used some of the properties of the ApplicationWindow (e.g. text size)?
I am new to coding and stack overflow (this is my first post). I've tried to ask my question in the clearest way possible, but please let me know if it's not up to par with stack overflow's standards and what I must do to change it.
Scope in QML is easy, maybe weird, but easy :
When you use an identifier, lets say foo
in a var binding, QML engine search in this order :
foo
as its IDfoo
as its IDfoo
foo
If it does not find it, it throws ReferenceError
.
And no, immediate parent or child is not in the scope. That can seem weird, but that's the way it works.
If you need an out-of-scope variable to be referenced, just use an ID before it : if the object is called foo
and has a property named bar
, you can reference foo.bar
wherever you wan't in the file.
Hope it helps.