Search code examples
qtcheckboxqmlqtquickcontrols2

Qt: checkbox single click not working


I'm playing around with QtQuick in Qt 5.9 and I encountered a strange issue. When I created two Tumblers and a CheckBox in QML everything was working fine.

But when I created an event handler for a id: secondTumbler which manipulates testCheckBox.checked status the CheckBox started to act in a strange way.

When I launch the app and firstly scroll around any tumbler and then click the CheckBox it will not check. The second click will eventually check it but that is a strange behavior.

The only thing I wrote is the below code in the main.qml:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Tumbler {
        id: firstTumbler
        model: 10
        anchors.left: parent.left
    }

    Tumbler {
        id: secondTumbler
        model: 10
        anchors.right: parent.right

        onCurrentIndexChanged: {
                testCheckBox.checked = false
        }
    }

    CheckBox {
        id: testCheckBox
        anchors.left: firstTumbler.right

        onCheckedChanged: {
            if(testCheckBox.checked == true)
            {
                secondTumbler.currentIndex = firstTumbler.currentIndex
            }
        }
    }
}

What am I missing?


Solution

  • The issue is that javascript runs asynchronously. So, signals and slots dont work as they do in C++. They fire along with the other code, not sequentially. This makes them an unrealiable Intermediary for logical processing since the order that events can happen can vary.

    Instead,

    Use property bindings for this one by setting a property such as currentIndex to another property created using property var <my property> and currentIndex: <my property>

    Then you can change the value of currentIndex by setting <my property> without disrupting the flow of things.

        Tumbler {
                id: firstTumbler
                model: 10
                anchors.left: parent.left
            } 
    
    
           /* Edit in response to comment #1 
            */
    
         property bool followFirst: testCheckbox.checked
    
    
           /* end of Edit in response to comment #1 */
    
            Tumbler {
                id: secondTumbler
                model: 10
    
    
                /* modify the property of currentIndex  by changing this variable which will be bound to the currentIndex property */
                property var m_index: 0
    
    
                anchors.right: parent.right
    
    
               /* conditional assignment for currentIndex -- do not set currentIndex directly or this will disappear.. 
      instead set secondTumbler.m_index */
                currentIndex: testCheckBox.checked === true ?    firstTumbler.currentIndex : m_index
    
                /* ensures that changing the currentIndex does not change the     actual property, but instead changes m_index which will be bound to that property */
                onCurrentIndexChanged: {
                       m_index = currentIndex;
    
    
    
    
                      /* Edit in response to comment #1 
                      */
    
                       if (followFirst) { testCheckBox.checked = false }
    
                      /* end of Edit in response to comment #1 */
                }
            }
    

    this will allow the chckbox to change state along with the tumbler without running into state conflicts arising from the current index changing.