Reputation: 972
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?
Upvotes: 0
Views: 760
Reputation: 972
I found a tricky and simple solution as the Pressed state occurs before the Clicked state;
Button {
...
...
onPressed: {
background.color = "orange"
}
onClicked: {
if(some_condition))
background.color = "green"
else
background.color = "red"
}
}
Thus, as soon as I press the button, the button color becomes orange and after the condition result is clear, the button color becomes red or green depending on the condition.
Upvotes: 0
Reputation: 25956
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:
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!
Upvotes: 1
Reputation: 984
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.
Thus, the plan is as follows.
Button
.Button
turns orange as well.Button
then turns green if Image
enters the ready state.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";
}
}
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";
}
...
}
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";
}
BusyIndicator
in the example: https://github.com/SMR76/qml-snow-white/blob/master/SnowWhite/BusyIndicator.qmlUpvotes: 1