qtqml

How to specify cursor location each time qml TextInput is clicked?


I am trying to overcome the problem a user will have designating their cursor location with their finger. For instance, lets say my user has no mouse and they want to delete a string entirely and replace it with a new one. So they push (click) the the TextInput box and the cursor puts them in the middle of the string. So what do they do? Well either they delete the first half of the string and then click the box again (attempting to land at the end of the string this time) or they immediately click again in an attempt to land at the end of the string.

I can see this getting very frustrating for someone with bad eyesight and fat fingers. Never mind the possibility that they are attempting to do this say in a tractor, bouncing around an open field in not so great lighting conditions with bad eyesight and fat fingers.

Instead, I want the cursor to always land at the end of the current string but I can not seem to find a good method of doing this with TextInput. I have found a work-around using a button:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4
import QtQuick.Controls 2.5

Window {
id: window
visible: true
width: 640
height: 480

Item{
    id: thisItemHere
    anchors.centerIn:  parent

    Button {
        id: button
        anchors.centerIn: parent
        text: qsTr("Button")
        onClicked: inputItem.forceActiveFocus()
    }

    TextInput{
        id:inputItem
        text: "Enter text here"
        visible: false

        EnterKeyAction.enabled: inputItem.text.length > 0 || inputItem.inputMethodComposing
        EnterKeyAction.label: "Next"

        Keys.onReleased: {
            if (event.key === Qt.Key_Return) {
                button.text = inputItem.text
                console.log(inputItem.text)
                //activeFocus = false not working...
            }
        }

        onActiveFocusChanged: {
            if(activeFocus) {
                inputPanelContainer.textDisplay = inputItem.text
            }
        }

        onDisplayTextChanged: {
            inputPanelContainer.textDisplay = text
        }
    }
}

InputPanelContainer {
    id: inputPanelContainer
    x: 0
    y: window.height
 }
}

I don't like having to use a work around. I have tried using the select all function:

onActiveFocusChanged: {
        selectAll()
        if(activeFocus) inputPanelContainer.textDisplay = inputItem.text
    }

however; I think in order for this to work I would need to find a good way of ending the focus because currently I cant seem to figure out how to end the focus once the user is done editing the string and so it only gets highlighted on the first interaction. In other words, after pressing enter the cursor is still in the TextBox, blinking.

So perhaps someone could tell me the proper way of ending focus or perhaps someone could tell me how to use the moveCursorSelection() or some other property, signal or method of TextInput that will cause the cursor location to always be at the end of the string once the user clicks the TextInput box?


Solution

  • Why do you try to catch the Return key yourself?

    I always use the already existent onEditingFinished signal for this, which works well normally.

    activeFocus is a read-only property, so that won't work indeed. You may try to forceActiveFocus on your thisItemHere item or even top-Window instead to release focus from the TextInput.

    Also, you may look at the cursorPosition property? Setting this to inputItem.length when gaining focus, should work?