Reputation: 155
I am searching for a logic, so that an Image source property is changed depending on some different conditions.
I have created a small example with three conditions and three requirements build by those conditions.
If a requirement is active I want to see its picture in the Image area. If a requirement is not active I do not want to see its image in the image area. If two requirements would be active at the same time, it is ok to see just one of them.
I have problems with the code, because in case one requirement gets inactive and another gets active at the same time, the last requirement will control the content. But I want to have a higher priority on showing an image than not showing an image.
Is there any frequent way how to solve this?
I have the following code:
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property bool condition1: false
property bool condition2: false
property bool condition3: false
Image{
id: image
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: 120
height: 120
source: ""
}
Row {
anchors.top: image.bottom
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: button1
text: "Condition1 = " + condition1
onClicked: condition1 = !condition1
}
Button {
id: button2
text: "Condition2 = " + condition2
onClicked: condition2 = !condition2
}
Button {
id: button3
text: "Condition3 = " + condition3
onClicked: condition3 = !condition3
}
}
StateObserver{
condition: condition1 && condition2 && condition3
bitmap: "Images/1.png"
target: image
}
StateObserver{
condition: !condition1 && condition2 && condition3
bitmap: "Images/2.png"
target: image
}
StateObserver{
condition: !condition1 && !condition2 && condition3
bitmap: "Images/3.png"
target: image
}
}
StateObserver.qml
import QtQuick 2.0
Item {
property bool condition
property string bitmap
property var target
onConditionChanged: {
if (condition){
target.source = bitmap
}
else {
target.source = ""
}
console.log("Change bitmap: " + bitmap)
}
}
Upvotes: 2
Views: 16066
Reputation: 155
By the comment of dtech I have created an example using states. This works like expected and I am able to separate the states(requirements) from the main.qml(Layout). Thanks!
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
id: mainApp
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property bool condition1: false
property bool condition2: false
property bool condition3: false
Image{
id: image
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: 120
height: 120
Img_StateList{
container: image
}
}
Row {
anchors.top: image.bottom
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: button1
text: "Condition1 = " + condition1
onClicked: condition1 = !condition1
}
Button {
id: button2
text: "Condition2 = " + condition2
onClicked: condition2 = !condition2
}
Button {
id: button3
text: "Condition3 = " + condition3
onClicked: condition3 = !condition3
}
}
}
Img_StateList.qml:
import QtQuick 2.0
Item {
property Image container;
state: "default"
states: [
State {
name: "default"
PropertyChanges {
target: container
source: ''
}
},
State {
name: "Img1"
when: condition1 && condition2 && condition3
PropertyChanges {
target: container
source: 'Images/1.png'
}
},
State {
name: "Img2"
when: !condition1 && condition2 && condition3
PropertyChanges {
target: container
source: 'Images/2.png'
}
},
State {
name: "Img3"
when: !condition1 && !condition2 && condition3
PropertyChanges {
target: container
source: 'Images/3.png'
}
}
]
}
Upvotes: 0
Reputation: 49329
I would not consider this a sound approach, as the order of binding expression evaluation is unspecified.
What I would do is have a single point that evaluates all possible combinations and use its result to rig the rest of the properties.
Through your StateObserver
you are basically introducing unnecessary complexity. You also don't account for every possible state configuration.
You could simply:
Image {
id: image
//...
source: {
if (condition1 && condition2 && condition3) return "Images/1.png"
else if (!condition1 && condition2 && condition3) return "Images/2.png"
else if (!condition1 && !condition2 && condition3) return "Images/3.png"
else return ""
}
}
That's less code and less objects, meaning lower ram and cpu usage.
But if you insist on using your current approach, you can use Binding
elements which can automatically toggle on or off using their when
property.
Finally, you can also use QML's own state machine, although for such a trivial case that would be overkill.
Upvotes: 2