简体   繁体   中英

How to manage Focus with States in my custom QML component?

I´ve created a draggable custom Component in order to manage the geometry of individual Quick Controls Components.

The componet has 2 parts:

  • The "Manipulator" which is a draggable and resizable Rectangle
  • The inner component which is in the center of the manipulator

Description of the behavior:

  1. No focus : the default state, the Manipulator is invisible and you can only see the inner component
  2. Focused : When you click the component (or try to drag it) you enter this state and the Manipulator becomes visible but you can´t access the inner component. Disabled pressing Escape or clicking outside the component (goes to state 1)
  3. Inner Focus : when you double click on the component The Manipulator keeps visible and you can still still resize but the the inner component has the main focus (for example a TextEdit now could be editable). Disabled pessing Escape (goes to state 2) or clicking outside the component (goes to state 1)

Example of the Component when the Manipulator area is visible

The logic of this component would be similar to the logic of a folder in a Desktop Enviroment (except for resizing) The manipulator would be the folder itself and the inner component is its name.

analogy with folder

Here I post a simplified version of my manipulator, I´m sure it will help to construct an answer, (I tried a lot of variations for several hours, this is one of those not functional attempts)

FocusScope{
    id: root
    width: 175; height: 25;
    focus: true

    states: [
        State {
            name: "noFocus"
            when: !manipulator.activeFocus && !innerComp.activeFocus
            PropertyChanges {
                target: innerComp
                enabled: false
            }
            PropertyChanges {
                target: manipulator
                visible: false
            }
        },

        State {
            name: "focused"
            when: manipulator.activeFocus
            PropertyChanges {
                target: innerComp
                enabled: false
            }
            PropertyChanges {
                target: manipulator
                visible: true
            }
        },
        State {
            name: "innerFocus"
            when: innerComp.activeFocus
            PropertyChanges {
                target: innerComp
                enabled: true
            }
            PropertyChanges {
                target: manipulator
                visible: true
            }
        }
    ]

    //visual area of manipulation (drag, redimension, etc)
    MouseArea{
        id: manipulator
        anchors.fill: parent

        onDoubleClicked: forceActiveFocus(innerComp) //go to state 3 "innerFocus"
        drag.target: manipulator

        Keys.onEscapePressed: forceActiveFocus(root) //I don´t think this is the correct to loose focus but I don´t know how to do that

        Rectangle {
            id: background
            anchors.fill: parent
            color: "lightsteelblue";
        }
    }
    //Inner Component (TextField for example)
    InnerComp {
        id: innerComp
        anchors.fill: parent

        Keys.onEscapePressed: forceActiveFocus(manipulator) //return state 2 "focused"
    }
}

I finally found the solution, as someone in a qt forum sugested:

Maybe reverse the dependency, ie make the focus depend on the state, not the state depend on the focus?

So I changed my code and now it works!

I post the solution here for those who could be interested in it (as I said this is a simplified version of the real code):

Item {
    id: root
    width: 175; height: 25;

    states: [
        State {
            name: "noFocus"

            PropertyChanges {
                target: innerComp; enabled: false
            }
            PropertyChanges {
                target: background; visible: false
            }
            PropertyChanges {
                target: manipulator; focus: true
            }
        },

        State {
            name: "focused"

            PropertyChanges {
                target: innerComp; enabled: false
            }
            PropertyChanges {
                target: background; visible: true
            }
            PropertyChanges {
                target: manipulator; focus: true
            }
        },
        State {
            name: "innerFocus"

            PropertyChanges {
                target: innerComp; enabled: true
            }
            PropertyChanges {
                target: background; visible: true
            }
            PropertyChanges {
                target: manipulator; focus: true
            }
        }
    ]
    state: "noFocus"

    //visual area of manipulation (drag, redimension, etc)
    MouseArea{
        id: manipulator
        anchors.fill: parent

        onPressed: {
            root.state = "focused"
            forceActiveFocus(manipulator) //this prevents loosing focus in some especific situations
        }
        onDoubleClicked: root.state = "innerFocus"

        Keys.onEscapePressed: root.state = "noFocus"

    }
    Rectangle {
        id: background
        anchors.fill: parent
        color: "lightsteelblue";
    }
    //Inner Component (TextField for example)
    InnerComp {
        id: innerComp
        anchors.fill: parent

        Keys.onEscapePressed: root.state = "focused"
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM