You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QML中Repeater更新时保持TextInput焦点的技术问询

解决QML Repeater更新后TextInput焦点丢失问题

这问题我太熟悉了!你遇到的焦点丢失问题,核心原因是直接替换Repeater的model时,所有原有delegate都会被销毁重建——你原来操作的那个TextInput已经不存在了,再给它设置焦点当然没用。下面给你两种可行的解决方案,推荐第一种更符合QML设计的方式:

方案一:改用ListModel(推荐)

放弃普通数组,用ListModel来管理数据,它支持动态添加/修改项,Repeater只会更新变化的部分,不会销毁原有输入框。同时用Qt.callLater延迟设置焦点,确保新项已经创建完成:

import QtQuick 2.11
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    ListModel {
        id: inputModel
        ListElement { text: "test1" }
        ListElement { text: "test2" }
        ListElement { text: "" }
    }

    Column {
        id: column
        anchors.fill: parent
        Repeater {
            id: repeater
            model: inputModel

            Rectangle {
                border.width: 1
                border.color: "black"
                width: column.width
                height: childrenRect.height

                TextInput {
                    id: textField
                    text: model.text
                    width: column.width

                    onTextEdited: {
                        // 更新当前项的文本
                        inputModel.setProperty(index, "text", text)

                        // 检查最后一项是否非空,是则添加新空项
                        const lastIndex = inputModel.count - 1
                        if (inputModel.get(lastIndex).text !== "") {
                            inputModel.append({ text: "" })
                            // 延迟获取新的最后一个输入框并设置焦点
                            Qt.callLater(() => {
                                const lastItem = repeater.itemAt(lastIndex + 1)
                                if (lastItem) {
                                    lastItem.textField.forceActiveFocus()
                                }
                            })
                        }
                    }
                }
            }
        }
    }
}

方案二:保留普通数组的修复方式

如果你坚持用普通数组,那需要在model更新后,找到新创建的最后一个TextInput来设置焦点,而不是原来的那个(因为原输入框已经被销毁):

import QtQuick 2.11
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    property var values: ['test1','test2',''];

    Column {
        id: column
        anchors.fill: parent
        Repeater {
            id: repeater
            model: values

            Rectangle {
                border.width: 1
                border.color: "black"
                width: column.width
                height: childrenRect.height

                TextInput {
                    id: textField
                    text: qsTr(modelData)
                    width: column.width

                    onTextEdited: {
                        values[index] = textField.text;
                        if(values[values.length - 1] !== '') {
                            values.push('');
                            repeater.model = values;
                            // 延迟获取新的最后一项并设置焦点
                            Qt.callLater(() => {
                                const lastItem = repeater.itemAt(values.length - 1)
                                if (lastItem) {
                                    lastItem.textField.forceActiveFocus()
                                }
                            })
                        }
                    }
                }
            }
        }
    }
}

关键说明

  • 为什么原来的focus设置无效?:当你执行repeater.model = values时,Repeater会销毁所有旧的delegate实例,重新创建所有项。你原来的textField已经不存在了,所以对它的焦点设置完全无效。
  • Qt.callLater的作用:Repeater更新model后,新项的创建是异步的,直接设置焦点可能会找不到新项。Qt.callLater会把焦点设置操作放到下一个事件循环,确保新项已经创建完成。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:45:43