1
votes

Here are the code in my QML files:

main.qml

Rectangle {
    id: window    
    color: "white"; width: 240; height: 150

    Column {
        anchors.centerIn: parent; spacing: 15

        MyClickableWidget {
            focus: true             //set this MyWidget to receive the focus
            color: "lightblue"
        }
        MyClickableWidget {
            color: "palegreen"
        }
    }    
}

MyClickableWidget.qml

FocusScope {
    id: scope
    //i try to set true instead of the mouse event
    //focus: true
    //FocusScope needs to bind to visual properties of the children
    property alias color: rectangle.color
    x: rectangle.x; y: rectangle.y
    width: rectangle.width; height: rectangle.height

    Rectangle {
        id: rectangle
        anchors.centerIn: parent
        color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true
        Text { id: label; anchors.centerIn: parent }
        focus: true
        Keys.onPressed: {
            if (event.key == Qt.Key_A)
                label.text = 'Key A was pressed'
            else if (event.key == Qt.Key_B)
                label.text = 'Key B was pressed'
            else if (event.key == Qt.Key_C)
                label.text = 'Key C was pressed'
        }
    }
    MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } }
}

I have two question about this code:

First. The first component have been set focus: true. Then when press key, it will show the text. But I am not clear that why clicking either MyClickableWidget gives it focus and the other widget loses the focus? Does the click event give the focus to the component? If yes, which part will get the focus (scope or rectangle)?

Also, in my opinion, the line showed as following is to set scope.focus to true. So, I comment out this line, the insert a line focus = true in the scope. However it doesn't work, can not pass the key focus to the other item. Why?

// MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } }

The result is the same. I don't know why the code need this line.

Second. In focus scopes, if the children have the focus: true, all parent and root will automatically be set focus: true? if not in focus scopes, is the same result?

1

1 Answers

2
votes

Why do you need a FocusScope in the first place? Your code can be greatly simplified if you get rid of it.

An important thing to know is that within a FocusScope, only one item at a time can have focus. The application window behaves like a FocusScope itself. To keep it simple, if an item gains focus, the item that previously had focus automatically loses it.

FocusRect.qml

Rectangle {
    width: 175;
    height: 25;
    radius: 10;

    Text { id: label; anchors.centerIn: parent }

    Keys.onPressed: {
        if (event.key == Qt.Key_A)
            label.text = 'Key A was pressed'
        else if (event.key == Qt.Key_B)
            label.text = 'Key B was pressed'
        else if (event.key == Qt.Key_C)
            label.text = 'Key C was pressed'
    }

    MouseArea
    {
        anchors.fill: parent
        onClicked: parent.forceActiveFocus()
    }
}

main.qml

ApplicationWindow {

    width: 960
    height: 540

    Column {
        anchors.centerIn: parent; 
        spacing: 15

        FocusRect {
            focus: true             //set this MyWidget to receive the focus
            color: "lightblue"
        }
        FocusRect {
            color: "palegreen"
        }
    }
}

The behavior here is stragihtforward. An item must have activeFocus to get key events. For an Item to have activeFocus set to true, two condition must be met

  • Item itself has its focus property set to true
  • Its closest FocusScope parent has activeFocus or it has no focusScope parent, and the application window has active focus.

In this simple example, setting the focus of MyClickableWidget to true will also set its activeFocus to true (no parent FocusScope), making it able to get KeyEvents.

In answer to your second question, within a FocusScope, setting an item's focus to true will have no side effects. However, forcing it to gain activeFocus (by calling forceActiveFocus() on it) will make all its FocusScope parents gain activeFocus (and consequently set focus to true for all FocusScope in the item's parent hierarchy)

Conversely, if a FocusScope gains active focus and have a child with focus set to true, the child activeFocus will also be set to true.