如何编写具有 return 值的 QML 键盘

HowTo write a QML-Keyboard with return value

我在我的 QML 应用程序的 ListView 中使用了很多 TextInput。要修改我提供的虚拟 QML 键盘的值,它还包含一个 TextInput。

当我单击 ListView 中的 TextInput 时,QML-Keyboard 中的 TextInput 获得焦点,用户可以开始编辑。完成后,文本应发送到 ListView 中的 TextInput。

我遇到的问题是,我不知道如何将键盘的 TextInput 的文本复制到 ListView 的 TextInput,因为启动虚拟键盘时焦点丢失了。

ListView 中的每个委托项都由其附加的 index 明确标识 属性。列表中的第一个委托的索引为 0,然后是 1,依此类推。

A ListView 有一个 属性 currentIndex 引用当前 selected 项目委托。当 currentIndex 设置为特定委托时,currentItem 属性 也设置为相应的委托对象。

鉴于这些属性,您可以利用它们来获得所需的行为。当你select一个TextInput编辑它时,你可以将列表的currentIndex设置为TextInput委托的索引。这样也设置了 currentItem,当虚拟键盘中的编辑完成时,它可以稍后用于引用委托(和内部的 TextInput)。

这里有一个例子可以更好地解释我的观点:

import QtQuick 2.3
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1

Window {
    width: 200
    height: 300

    visible: true

    Component {
        id: myDelegate
        Rectangle {
            width: myList.width; height: 20
            color: myList.currentIndex === index ? "lightgreen" : "lightgray"  // distinguish the selecte delegate 
            onFocusChanged: textInput.forceActiveFocus()
            property alias textInput: textInput     // alias the textInput   // (1)

            TextInput  {
                id: textInput
                anchors.fill: parent

                onCursorVisibleChanged: {
                    if(cursorVisible)
                    {
                        myList.currentIndex = index   // (2)
                        keyboardInput.text = textInput.getText(0, textInput.text.length) // (3)
                        keyboardInput.forceActiveFocus()
                    }
                }
            }
        }
    }

    ColumnLayout {
        anchors.fill: parent

        ListView {
            id: myList
            model: 5
            delegate: myDelegate
            spacing: 10
            Layout.fillWidth: true
            Layout.fillHeight: true
        }

        Rectangle {
            Layout.alignment: Qt.AlignBottom
            color: "steelblue"
            Layout.preferredWidth: parent.width
            Layout.preferredHeight: 40
            TextInput  {
                anchors.centerIn: parent          // simulate the keyboard
                id: keyboardInput
                width: parent.width
                font.pixelSize: parent.height
                onEditingFinished: {
                    myList.currentItem.textInput.text = getText(0, text.length)   //(4)
                }
            }
        }
    }
}

这是一个简化的示例,其中您的虚拟键盘被 ID 为 keyboardInput 的蓝色 TextInput 替代。每次列表中的 TextInput 获得焦点时,焦点将传递给 keyboardInput 以编辑文本。

首先,委托中的 TextInput 是别名 (1),以便可以从委托外部访问。当列表中的 TextInput 获得焦点进行编辑时(在我的例子中,我考虑 CursorVisibleChanged 事件),列表 currentIndex 被设置为委托的 index (2 ) 并且 TextInput 中的当前文本也被复制到 keyboardInput (3) 中。编辑完成后,keyboardInput 中的文本将通过 currentitem (4).

复制回当前 selected TextInput

这种方法甚至适用于多个 ListView:只需将当前列表存储在更高范围的变量中,然后在 (4) 中引用该变量以在正确的委托中设置文本。