Solved Focus issue in SwipeView with Loader
-
Hello Qt developers :),
I have problem with proper setting the focus of the Item. There is SwipeView which contains 2 pages. One of these pages ihas Loader. Here how the qml file looks like:
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") objectName: "AppWindow" FocusScope { anchors.fill: parent focus: true SwipeView { id: swipeView objectName: "SwipeView" anchors.fill: parent currentIndex: tabBar.currentIndex Rectangle { Loader { id: pageLoader anchors.centerIn: parent focus: true } } Page { Label { text: qsTr("Second page") anchors.centerIn: parent } } } } footer: TabBar { id: tabBar currentIndex: swipeView.currentIndex TabButton { text: qsTr("First") } TabButton { text: qsTr("Second") } } Component.onCompleted: { console.log("App Window OnCompleted") pageLoader.setSource("Page1.qml") // pageLoader.forceActiveFocus() } }
And there is also "Page1.qml":
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 Item { objectName: "Page1 Item" property alias textField1: textField1 property alias button1: button1 RowLayout { objectName: "Page1 RowLayout" anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20 anchors.top: parent.top TextField { id: textField1 objectName: "TextField1" placeholderText: qsTr("Text Field") focus: true } Button { id: button1 text: qsTr("Press Me") } } Component.onCompleted: { console.log("Page1 onCompleted") // textField1.forceActiveFocus() } }
I would like to have to focus inside the TextField so just after the application start I can type somethig with my keyboard. I would like to get this focus without using methods like Item.forceActiveFocus() etc. Best solution for me would be to use FocusScope and focus property.
Do you have any clue how to properly setup FocusScope, SwipeView and Loader?
-
@poor_robert
Your pages are inside aSwipeView
, whose pages are made children of itscontentItem
and thus set both the focus of theSwipeView
and itscontentItem
totrue
(somehow, setting onlycontentItem.focus
totrue
does not work. Also set theLoader
's focus totrue
. The following works without using anyforceActiveFocus()
:- Eliminate the
FocusScope
in yourApplicationWindow
: not needed:
ApplicationWindow { ... //Get rid of this, no use FocusScope { } }
- Then:
SwipeView { id: swipeView objectName: "SwipeView" anchors.fill: parent currentIndex: tabBar.currentIndex focus: true contentItem.focus: true Page { Loader { focus: true id: pageLoader anchors.centerIn: parent source: "page1.qml" } } Page { Label { text: qsTr("Second page") anchors.centerIn: parent } } }
Loader
is itself aFocusScope
, so if you don't want to force focus on individual elements of your loaded page, you can still force it upon theLoader
as a whole, and let theLoader
's internalFocusScope
do its job. Then you don't need to set the focus on theSwipeView
and itscontentItem
:Loader { focus: true id: pageLoader anchors.centerIn: parent source: "page1.qml" onLoaded: forceActiveFocus() }
Also, as a side note, why don't you simplify your
Page1.qml
as follows:RowLayout { objectName: "Page1 RowLayout" anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20 anchors.top: parent.top TextField { id: textField1 objectName: "TextField1" placeholderText: qsTr("Text Field") focus: true } Button { id: button1 text: qsTr("Press Me") } }
No need to wrap it in a superfluous
Item
, unless of course, you have other plans... I used to do such unnecessary wrapping myself when I started learning QML not so long ago... - Eliminate the
-
@Diracsbracket Thank you, this works as expected :).