My goal is that when the button is clicked, the button color changes to orange and stays orange until the result of the if condition is declared. Then I want the button color to be green if the condition is met and red if not. However, when I click the button, the button color does not change until the condition result is clear, and when the condition is certain, the button color becomes either green or red. So the button color never turns orange.
I have shown my button usage below;
Button
{
...
...
onClicked: {
background.color = "orange"
if(some_condition))
background.color = "green"
else
background.color = "red"
}
}
NOTE: I am sending data to a device in an if condition and waiting for its response(this takes about 1-2 seconds). I expect the button to be orange until the answer comes, green if my condition is true after the answer, and red if it is false. But the color of the button does not turn orange.
Do you have any suggestions?
CodePudding user response:
To achieve this, property bindings must be used.
In this example, I'll use Image
to demonstrate your loading thing.
For this example, I am providing two methods.
Method one
Thus, the plan is as follows.
- I press the
Button
. - The image's source changes, and it goes to the loading state.
And theButton
turns orange as well. - The
Button
then turns green ifImage
enters the ready state. - Or else, the
Button
turns red.
Grid {
columns: 1
Image {
id: img
width: 200; height: 200
fillMode: Image.PreserveAspectFit
}
Button {
palette.button: img.status == Image.Loading ? "orange" :
img.status == Image.Ready ? "green" :
img.status == Image.Error ? "red" : "#259bd7"
onClicked: img.source = "https://thispersondoesnotexist.com/image";
}
}
Method two
Similar to method one in most ways, but not declaratively.
I press the Button
, and the Button
turns green or red anytime the image status changes.
Grid {
columns: 1
Image {
id: img
width: 200; height: 200
fillMode: Image.PreserveAspectFit
onStatusChanged: {
if(status == Image.Ready) btn.palette.button = "green";
else if(img.status == Image.Error) btn.palette.button = "red";
}
}
Button {
id: btn
palette.button: "#259bd7"
onClicked: {
palette.button = "orange"
img.source = "https://thispersondoesnotexist.com/image";
}
}
}
Now, if for some weird reason, you want to do everything in the button, you can put a boolean property and change the color as it changes.
Like:
Image {
...
onStatusChanged: {
// some code and calculation
btn.condition = // true or false
}
}
Button {
...
property bool condition
onConditionChanged: {
if(condition) palette.button = "green";
else palette.button = "red";
}
...
}
Example.qml
Okay, so we now know what the answer is, well let's improve it (In the case that a lazy programmer wants to copy :D).
Image.status
is an Enum with values ranging from 0 to 3.
Image {
id: img
width: 200; height: 200
fillMode: Image.PreserveAspectFit
}
Button {
id: btn
implicitHeight: 30
property list<Item> content: [
Item {},
Text { text: " ✓" },
BusyIndicator { running: true },
Text { text: " ✖" }
]
contentItem: Item {
width: parent.implicitWidth
Grid {
x: (parent.width - width)/2
spacing: 6
Text { text: "button" }
Control { contentItem: btn.content[img.status] }
Behavior on x { SmoothedAnimation {}}
}
}
onClicked: img.source = "https://thispersondoesnotexist.com/image";
}
Preview
BusyIndicator
- The
BusyIndicator
in the example: https://github.com/SMR76/qml-snow-white/blob/master/SnowWhite/BusyIndicator.qml - https://github.com/Furkanzmc/QML-Loaders
CodePudding user response:
In this answer, I manipulate Button
background
by setting it to a Rectangle
and I control the Rectangle
's color to iterate between (1) default button color, (2) orange, (3) red and (4) green. Hence, I identified there are 4 unique states as detailed as follows:
- button hasn't been clicked yet, the button background color is the default color
- button has been clicked, but the user hasn't typed anything, the button background changes to an "orange" color
- the text has been entered, but the answer is wrong, the button color changes to "red" color
- the text has been entered, and the answer is correct. the button background changes to "green" color
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
property bool started: false
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 10
Label {
visible: started
text: qsTr("What is 1 1?")
}
Frame {
Layout.fillWidth: true
visible: started
TextEdit {
id: answer
width: parent.width
}
}
Button {
background: Rectangle {
color: started
? answer.text
? answer.text === "2"
? "green"
: "red"
: "orange"
: palette.button
}
text: qsTr("Start")
onClicked: {
if (!started) {
started = true;
answer.text = "";
} else {
started = false;
}
}
}
}
}
You can Try it Online!