Animate color in QML when C++ binding variable in modified



  • Hello everyone,

    Do you know how can I animate a Rectangle color property in QML when a C++ binding has been modified?

    my qml part look like this :
    @
    Rectangle
    {
    id : power_cons_tile
    // I want to animate the color when the new color is used
    color : model.power_cons < 100 ? "#008A00" : "#E51400"
    height: 85
    width : 175
    smooth: true
    ...
    @



  • Could you also post related C++ code?



  • It doesn't make sense to me to animate the color like that since you haven't given an initial color. That is, you are assigning either the green or the red color and it will be the initial color so there's nothing to animate to. But if power_cons were to change later, then you could animate the color using states.

    Here's a small demo using height instead of model.power_cons. When the height of the rectangle changes (you can just drag the window in this case) the onHeightChanged() signal will be sent. When the height of the rectangle becomes higher than 100, the state will be changed to "red", when it becomes lower than 100 it will change back to the default state "".

    @import QtQuick 2.0

    Rectangle
    {
    id: power_cons_tile
    // I want to animate the color when the new color is used
    color: "#008A00" //"#E51400"
    height: 85
    width: 175
    smooth: true

    onHeightChanged: {
        if(height >= 100)
            state = "red";
        else
            state = "";
    }
    
    states: [
        State {
            name: "red"
            PropertyChanges {
                target: power_cons_tile
                color: "#E51400"
            }
        }
    ]
    
    transitions: [
        Transition {
            from: ""
            to: "red"
            ColorAnimation {
                duration: 400
                easing.type: Easing.InOutQuad
            }
        },
        Transition {
            from: "red"
            to: ""
            ColorAnimation {
                duration: 400
                easing.type: Easing.InOutQuad
            }
        }
    ]
    

    }
    @

    Hopefully, this will point you in the right direction, even if it's not exactly what you're looking for.



  • Here is the C++ code :

    @
    #include "Model.h"

    Model::Model()
    {
    m_temperature = 0;
    m_power_cons = 0;

    temp = new Temperature();
    pwr = new Power_Cons();

    QObject::connect(&timer_temp, SIGNAL(timeout()), this, SLOT(getTemperatureFromSensor()));
    QObject::connect(&timer_pwr, SIGNAL(timeout()), this, SLOT(getPower_ConsFromSensor()));

    timer_temp.start(500);
    timer_pwr.start(3000);
    }

    void Model::getTemperatureFromSensor()
    {
    setTemperature(temp->temperature_sensor());
    }

    void Model::getPower_ConsFromSensor()
    {
    setPower_Cons(pwr->power_cons_sensor());
    }

    int Model::getTemperature()
    {
    return m_temperature;
    }

    int Model::getPower_Cons()
    {
    return m_power_cons;
    }

    void Model::setTemperature(int c)
    {
    if(c!=m_temperature)
    {
    m_temperature = c;
    emit temperatureUpdated();
    }
    }

    void Model::setPower_Cons(int c)
    {
    if(c!=m_power_cons)
    {
    m_power_cons = c;
    emit power_consUpdated();
    }
    }
    @

    Why should I initiate a color with a value since the binding does it?
    My aim is only to (smoothly) change the color of the rectangle from green to red when the power consumption is higher than a certain value.
    You will agree, this is a correct Use Case.



  • Well if you don't want to animate it initially (it wouldn't make sense anyway), then it might be better to bind the power consumption to a custom property called e.g. powerConsumption and use states for animation. Something like this (I'm using height as a dummy for powerConsumption):

    @import QtQuick 2.0

    Rectangle
    {
    id: power_cons_tile
    // I want to animate the color when the new color is used
    color: "#008A00" //"#E51400"
    height: 85
    width: 175
    smooth: true

    property alias powerConsumption: power_cons_tile.height
    
    onPowerConsumptionChanged: {
        if(powerConsumption >= 100)
            state = "red";
        else
            state = "";
    }
    
    states: [
        State {
            name: "red"
            PropertyChanges {
                target: power_cons_tile
                color: "#E51400"
            }
        }
    ]
    
    transitions: [
        Transition {
            from: ""
            to: "red"
            ColorAnimation {
                duration: 400
                easing.type: Easing.InOutQuad
            }
        },
        Transition {
            from: "red"
            to: ""
            ColorAnimation {
                duration: 400
                easing.type: Easing.InOutQuad
            }
        }
    ]
    

    }
    @



  • Okay, Thnaks a lot, I understand.
    I will try it then. But can you please explain more why I should use a custom property.
    I am guessing, maybe the QML doesn't evaluate expressions? Espacially when I do :
    @
    color : model.power_cons < 100 ? "#008A00" : "#E51400"
    @
    Are you saying that when the binding updates the value within
    @
    model.power_cons
    @

    the expression is not evaluated, so an animation is not applicable on it?



  • I am not sure how it would work with model.power_cons, but you would need to react to the change of the power consumption, not the change of color, because if the color has already changed, then it makes no sense to animate it anymore (it has already changed to the destination color).

    If you don't want to use a custom property, then maybe you could make a C++ signal for when the power consumption changes and then handle the signal in QML. I've never tried that, so I don't know how you would go about doing that.



  • bq.
    you would need to react to the change of the power consumption, not the change of color, because if the color has already changed, then it makes no sense to animate it anymore (it has already changed to the destination color).

    this is logic.
    I tested it, and it does work.

    Thanks a lot


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.