Search code examples
qmlqt5qtquick2qtquickcontrols

Enabled property of QML widget blocked by attached action


I want to enable button when TextField has acceptable text (I'm using the validator), and this code is working fine:

import QtQuick 2.3
import QtQuick.Controls 1.2

ApplicationWindow {
    visible: true
    width: 400
    height: 100
    id: mainWindow
    property int _buttonSize: 30
    property int _interval: 10

    TextField {
        y: _interval
        width: parent.width
        height: _buttonSize
        id: ipInput
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
        placeholderText: "IP"
        validator: RegExpValidator
        {
            regExp:/^(([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))\.){3}([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))$/
        }
    }

    Button {
        enabled: ipInput.acceptableInput
        id: go
        anchors.horizontalCenter: parent.horizontalCenter
        y: ipInput.y+_buttonSize+_interval
        width: parent.width
        height: _buttonSize
        text: "GO"
    }
}

So, I add the Action to this Button:

Button {
    enabled: ipInput.acceptableInput
    id: go
    anchors.horizontalCenter: parent.horizontalCenter
    y: ipInput.y+_buttonSize+_interval
    width: parent.width
    height: _buttonSize
    text: "GO"
    action: goAction
    Action {
        id: goAction
        shortcut: "Enter"
        enabled: go.enabled && go.visible
        onTriggered: {
            console.log("good")
        }
    }
}

And now the Button is always disabled. How I can fix it?


Solution

  • Actions work by synchronising the state of all the Items to which they are bound. The documentation says:

    In applications many common commands can be invoked via menus, toolbar buttons, and keyboard shortcuts. Since the user expects each command to be performed in the same way, regardless of the user interface used, it is useful to represent each command as an action.

    An action can be bound to a menu item and a toolbar button, and it will automatically keep them in sync. For example, in a word processor, if the user presses a Bold toolbar button, the Bold menu item will automatically be checked.

    In this sense, the Action properties rules over the properties of the Items to which it is bound and not the vice versa. When the Action is enabled also all the Items to which it is attached, are enabled. Hence, the enabling condition should be moved to the Action.

    Here is a revisited version of your code. I've added another Button to stress the Action functionality. Here both the Buttons automatically enables when the condition is met, since it's the associated Action to become enabled.

    import QtQuick 2.3
    import QtQuick.Controls 1.2
    
    ApplicationWindow {
        visible: true
        id: mainWindow
    
        Column {
            spacing: 10
            TextField {
                width: 400
                height: 40
                id: ipInput
                horizontalAlignment: TextInput.AlignHCenter
                placeholderText: "IP"
                validator: RegExpValidator {
                    regExp:/^(([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))\.){3}([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))$/
                }
            }
    
            Action {
                id: goAction
                shortcut: "Enter"
                enabled: ipInput.acceptableInput
                onTriggered: {
                    console.log("good")
                }
            }
    
            Button {
                id: go
                width: 400
                height: 40
                text: "GO"
                action: goAction
            }
    
            Button {
                id: go2
                width: 400
                height: 40
                text: "GO2"
                action: goAction
            }
        }
    }