qtqtquickcontrols

qt qml checkbox: How to execute code when clicked by user but not checked by q_property binding


I have a checkbox in qt which I'd like to be checked via a q_property tied to code, but also by a user. When a user clicks on the checkbox, I'd like to run some code. The issue is that the onChecked callback seems to be called when the checkbox is checked via code as well as user input. This code would involve the checkbox being checked by code at a later time, which would trigger the onChecked callback. How is this situation best handled with the callbacks provided by Qt?

For more background if the above doesn't make sense: This checkbox controls a feature on a robot over a network connection, but it should also show the state of the feature since it could be enabled automatically or from a previous session. The q_property robotStatus.missionLooping is set by a periodic status update. When the user checks the box, it should trigger a network call to enable the feature, and then the status update will happen a moment later which would see that the feature is enable and check the box (Even though it's already checked).

AppCheckBox.qml:

import QtQuick 2.15
import QtQuick.Controls 2.15

CheckBox
{
    id: root

    indicator: Rectangle
    {
        implicitWidth: utilities.dp(40)
        implicitHeight: utilities.dp(40)
        x: root.leftPadding
        y: parent.height / 2 - height / 2

        Rectangle
        {
            width: utilities.dp(20)
            height: utilities.dp(20)
            x: utilities.dp(10)
            y: utilities.dp(10)
            radius: utilities.dp(3)
            color: theme.green
            visible: root.checked
        }
    }

    contentItem: Text
    {
        text: root.text
        font: root.font
        opacity: enabled ? 1.0 : 0.3
        color: theme.white
        verticalAlignment: Text.AlignVCenter
        leftPadding: root.indicator.width + root.spacing
        //font.pointSize: constants.coordinatesTextPointSize + 1
        minimumPointSize: constants.minimalCoordinatesTextPointSize
    }
}

ui.qml:

    AppCheckBox
    {
        id: missionLoopingCheckbox
        enabled: isConnected
        checked: robotStatus.missionLooping
        text: qsTr("Mission Looping")
    }

Solution

  • You can implement onToggled signal handler. toggled signal is emitted when a checkable button is interactively toggled by the user via touch, mouse, or keyboard.

    I'm assuming below that robotStatus.missionLooping is a readonly property. You need Q_INVOKABLE method or a slot function to call e.g. robotApi.loopMission(bool) which calls robot over the network and in turn causes robotStatus.missionLooping property to change to true/false when looping starts/stops.

    AppCheckBox
    {
        id: missionLoopingCheckbox
        enabled: isConnected
        checked: robotStatus.missionLooping
        text: qsTr("Mission Looping")
        onToggled: {
            robotApi.loopMission(missionLoopingCheckbox.checked)
        }
    }