Rob
Rob

Reputation: 555

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?

Upvotes: 0

Views: 2912

Answers (2)

Davronito
Davronito

Reputation: 31

I faced the same problem with desktop application. I managed to solve it with MouseArea, but I haven't tried it and have no idea whether it works with touch display or not.

I passed the mouse events to the parent exactly what it should have done without MouseArea clicked:

TextInput {
                        id: loginInput
                        anchors.verticalCenter: parent.verticalCenter
                        leftPadding: 8
                        topPadding: 4
                        width: parent.width*0.8
                        height: 20
                        KeyNavigation.tab: passwordInput
                        font.pixelSize: 12
                        Text {
                            id:loginPlaceholder
                            anchors.fill: parent
                            leftPadding: parent.leftPadding
                            topPadding: parent.topPadding
                            text: "Input Login..."
                            color: "#aaa"
                            visible: !parent.text
                            font.italic: true
                        }

                        MouseArea {
                            anchors.fill: parent
                            cursorShape: Qt.IBeamCursor
                            propagateComposedEvents: true
                            onClicked: {
                                mouse.accepted = false
                                parent.focus=true
                                parent.cursorPosition=parent.positionAt(mouseX,mouseY)
                            }
                            onDoubleClicked: parent.selectAll()
                        }
                    }

On my onDoubleClicked event it does that action what you asked for. You can move it to onClicked event.

Upvotes: 0

Bartel
Bartel

Reputation: 411

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?

Upvotes: 1

Related Questions