基础用法之外,ComboBox 还有两类很实用的用法:可编辑的下拉框以及运行时动态增删的选项(数据来自后端或用户操作)。这篇的两个 demo 分别演示这两种场景,并顺带讲清 JS 数组模型的更新机制。
- 可编辑 ComboBox ---
editable: true+ 正则校验,回车时自动去重添加新选项 - 动态更新模型 ---
Qt.callLater模拟异步加载,按钮实时追加选项
Demo 1:可编辑 ComboBox
需求:用户既能从下拉列表选,也能直接输入自定义值,输入合法就把它加进选项里,下次还能再选。这正好是"标签输入""搜索历史"类功能的雏形。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
ComboBox {
id: cbox
Layout.fillWidth: true
Layout.preferredHeight: 30
editable: true
model: ["100"]
validator: RegularExpressionValidator {
regularExpression: /^[A-Za-z0-9_]+$/
}
onAccepted: {
if (cbox.find(editText) === -1) {
model = model.concat(editText)
}
}
}
Text {
Layout.fillWidth: true
color: "#333"
font.pointSize: 11
text: "当前输入: " + cbox.editText
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
editable: true--- 把 ComboBox 变成"可选 + 可输入"的混合控件,内部实际是一个文本框加下拉按钮。此时editText就是用户当前输入的文本,实时更新。validator: RegularExpressionValidator--- 挂在 ComboBox 上即可限制输入内容,这里只允许字母、数字、下划线。注意:validator 不通过时回车无效 ,onAccepted不会触发,所以处理器里可以放心执行添加逻辑。onAccepted--- 用户按下回车时触发。处理流程是"先查重再追加":cbox.find(editText)--- 在现有选项里查找输入文本,返回索引;返回-1表示不存在。model = model.concat(editText)--- 把新文本追加进选项。这里必须整体重新赋值model属性,数组模型只有整体替换才会通知视图刷新(直接model.push()改原数组是不生效的,下一篇还会再强调)。
editText和currentText的区别:editText是正在输入的文本,currentText是当前选中项的文本;编辑中二者可能不同。
适用场景:允许用户自定义选项的表单、快捷标签输入、搜索历史记忆。
Demo 2:动态更新模型
选项数据通常不是写死的:可能来自网络请求,也可能在运行中被用户添加。这个 demo 用 Qt.callLater 模拟一次异步加载,再用一个按钮演示运行时追加选项。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
RowLayout {
Layout.fillWidth: true
spacing: 10
ComboBox {
id: dynamicCombo
Layout.fillWidth: true
Layout.preferredHeight: 30
Component.onCompleted: {
// 模拟异步加载数据
Qt.callLater(function() {
dynamicCombo.model = ["动态加载1", "动态加载2", "动态加载3"]
})
}
}
Button {
Layout.preferredHeight: 30
text: "添加选项"
onClicked: {
if (dynamicCombo.model instanceof Array) {
var newModel = dynamicCombo.model.slice()
newModel.push("新选项" + (newModel.length + 1))
dynamicCombo.model = newModel
}
}
}
}
Text {
id: textResult
Layout.fillWidth: true
color: "#333"
font.pointSize: 11
text: dynamicCombo.currentIndex >= 0
? "当前选择: " + dynamicCombo.currentText
: "未选择"
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
Qt.callLater(fn)--- 把函数推迟到当前事件循环处理完后再执行,用来模拟"数据到达"的时刻。真实项目中这里换成网络回调、数据库查询结果即可,机制完全一样。Component.onCompleted--- 组件创建完成后执行,是最常见的"初始化时加载数据"入口。- "添加选项"按钮的三步是 JS 数组更新的标准套路:
dynamicCombo.model instanceof Array--- 防御性判断,确认当前模型是数组(避免对 ListModel 等对象误操作)。var newModel = dynamicCombo.model.slice()--- 先拷贝出一份新数组,不要直接改原数组。newModel.push(...)后整体dynamicCombo.model = newModel--- 重新赋值触发下拉列表刷新。
- 演示里"新选项"的编号用
newModel.length + 1计算,保证每次添加都不重名。
适用场景:选项来自后端接口、级联选择(选省后动态加载市)、运行时允许用户扩充选项。
运行验证
- 用 Qt Creator 打开
qml_combobox/CMakeLists.txt; - 按
Ctrl+R运行; - "进阶用法"下切到"可编辑 ComboBox":输入合法字符回车,选项被添加;输入非法字符(如空格)回车无反应。
- 切到"动态更新模型":下拉框先短暂为空再出现选项(异步加载效果),点"添加选项"看列表增长。
扩展复用方向
- 可编辑框加个去重提示:
onAccepted里发现find() !== -1时弹出提示,而不是静默忽略。 Qt.callLater换成真实异步时,配合BusyIndicator显示加载状态,数据到了再赋值model。- 动态增删可以再加"删除选项"逻辑:
splice后整体重新赋值,与添加是对称的。
已验证环境:
- Qt 版本:Qt 6.8.2 / Qt 6.11.1
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_combobox