3

I want to enable TextField focus when QML file is loaded. But, it is not working. After loading TestUi.qml file I put some button and its onClick() method I did _recipientView.focus = true_, it works fine. The problem is that default focus is not enabled when view is loaded first time.

TestUi.qml

import QtQuick 2.0
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.0


Page {

    function init() {
        recipientView.focus = true;
    }

    TextField {
       id: recipientView
        Layout.fillWidth: true
        font.pixelSize: 18
        inputMethodHints: Qt.ImhNoPredictiveText | Qt.ImhEmailCharactersOnly
        focus: true
        placeholderText: "Email"
    
    }
}

main.qml

onComposeBtnClicked: {
    rootStackView.push(test)
    test.init()
}

TestUi {
    id: test
    visible: false
}
AAEM
  • 1,837
  • 2
  • 18
  • 26
nAkhmedov
  • 3,522
  • 4
  • 37
  • 72

1 Answers1

9

Edit

The Page component already acts as a FocusScope, so only forcing the active focus is necessary. Thanks for the comments.

StackView {
    id: stackView
    initialItem: firstPage

    // Ensures the focus changes to your page whenever
    // you show a different page
    onCurrentItemChanged: {
        currentItem.forceActiveFocus()
    }
}

Page {
    id: firstPage
    visible: false

    TextField {
        // Explicitly set the focus where needed
        focus: true
    }
}

Original answer

This is simply because you are pushing TestUi into your stack with rootStackView.push(test). When you do so, the focus is reset. This is typically handled with a QFocusScope, which role is to remember the focused Item, and give the focus back to it when the QFocusScope regains focus.

In your case, adding a QFocusScope to your base page would enable restoring the focus correctly when the page is shown:

StackView {
    id: stackView
    initialItem: firstPage
    onCurrentItemChanged: {
        currentItem.forceActiveFocus()
    }
}

Page {
    id: firstPage
    visible: false
    onFocusChanged: {
        scope.focus = true
    }
    FocusScope {
        id: scope
        TextField {
            focus: true
            // ...
        }
    }
}

You can then use your page handler onVisibleChanged if you want to reset to focus when the user comes back to it (after a pop for instance), instead of memorizing it where the focus is. But in that case the FocusScope might be overkill.

For information, you can also use the StackView property initialItem in order to set the first page.

It is also kind of unrelated, but prefer importing the most recent version of the QtQuick components available. QtQuick version will be 2.12 for Qt 5.12. A bit less trivial for QtQtcuik.Controls version, but they are getting in line with that versioning scheme.

Adrien Leravat
  • 2,731
  • 18
  • 32
  • I have to set focus not to the main Page. For me worked just adding onCurrentItemChanged: { currentItem.forceActiveFocus() } To main.qml. And adding Focus.scope to my target file caused an error. – KOHTPOJIEP Jan 03 '18 at 15:28
  • For me adding onCurrentItemChanged was enough aswell. There are some QML items like Page that act as focus scopes themselves. (a list of those items can be found here: https://doc.qt.io/qt-5/qtquickcontrols2-focus.html) – Tom Feb 21 '19 at 21:37
  • Thanks for the feedbacks. I don't remember if at the time, it was necessary, I will edit the answer regardless. – Adrien Leravat Feb 23 '19 at 18:21