写界面的时候,数字输入框是个躲不开的东西:调数值相关的活都绕不开它。这篇介绍 SpinBox 的基础用法和步长控制,看完这两个例子,大部分数字输入场景都能直接复用。
- 基础 SpinBox --- 可编辑模式配合输入验证,数值大了还能按千分位显示
- 自定义步长 SpinBox --- 用下拉框动态切换步长,数值带单位(角度 °)也不怕
Demo 1:基础 SpinBox
一个最普通的 SpinBox,打开可编辑模式后可以直接敲数字,超出范围会被拦下,数值显示成千分位。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
SpinBox {
id: spinBox
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 20
implicitWidth: 140
implicitHeight: 30
from: 0
to: 100
editable: true
// 输入验证
validator: IntValidator {
bottom: spinBox.from
top: spinBox.to
}
// 数值显示格式化
textFromValue: function(value, locale) {
return Number(value).toLocaleString(locale, 'f', 0)
}
}
Text {
Layout.alignment: Qt.AlignHCenter
text: "当前值:" + spinBox.value
font.pointSize: 11
color: "#333"
}
Text {
Layout.fillWidth: true
color: "#999"
font.pointSize: 10
text: "提示:可编辑模式可直接输入数字,超出范围会被验证器拒绝"
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
SpinBox 默认只能点加减按钮,一个数一个数地按太费劲。
editable: true 打开后可以直接键盘输入,再用 from / to 把范围限定在 0~100。
输入能不能被接受,由 validator 说了算。这里用的是 IntValidator,意思很直白:只能填整数,而且必须在 from 到 to 之间。手滑输了 101 或者 3.5,都会被拦下来。
textFromValue 的作用是把内部数值翻译成界面文字。默认直接显示数字,但数值一大(比如 1000)就不太好读,这里用 Number.toLocaleString 转成千分位显示成 "1,000"。locale 参数直接从 SpinBox 上取,格式会跟着系统的区域设置走,中文环境下就是逗号分隔。
有个细节值得注意:textFromValue 只影响显示,内部存的 value 还是 1000。后面做计算、保存都用 value,不用操心显示格式的事。
Demo 2:自定义步长 SpinBox
很多数值不光是整数那么简单,比如角度要带个 °,百分比要带个 %。这个例子做两件事:给数值加单位,用下拉框动态切换步长。

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
RowLayout {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: 20
spacing: 10
SpinBox {
id: spinBox
implicitHeight: 30
from: -100
to: 100
stepSize: 10
value: 0
editable: true
// 自定义显示格式:在数值后追加 °
textFromValue: function(value, locale) {
return value + "°"
}
// 自定义输入解析:去除 ° 后转为数字
valueFromText: function(text, locale) {
return Number.fromLocaleString(locale, text.replace("°", ""))
}
}
// 步长控制
ComboBox {
id: stepControl
implicitHeight: 30
model: ["1", "5", "10", "15", "20"]
onCurrentTextChanged: {
spinBox.stepSize = Number(currentText)
}
}
}
Text {
Layout.alignment: Qt.AlignHCenter
text: "当前值:" + spinBox.value + "°,步长:" + spinBox.stepSize
font.pointSize: 11
color: "#333"
}
Text {
Layout.fillWidth: true
color: "#999"
font.pointSize: 10
text: "提示:通过 ComboBox 可切换步长,支持 -100 到 100 的角度范围"
}
Item { Layout.fillHeight: true }
}
}
关键逻辑解析
带单位的 SpinBox 要成对写两个回调:
textFromValue:显示时把30变成"30°";valueFromText:输入时把"45°"里的°去掉,还原成数字 45。
一进一出,正好是互逆的两步。只写 textFromValue 的话,显示没问题,但用户一输入就解析失败------控件不知道该拿 "45°" 怎么办。
单位字符用 text.replace("°", "") 去掉,简单直接。想换成 %、px、℃,改这一处字符串就行。
步长切换的思路:让 stepSize 跟着下拉框走。ComboBox 的 onCurrentTextChanged 接口里,把选中的文本转成数字赋给 spinBox.stepSize,选 "10" 后点一次加号就跳 10。注意 stepSize 只支持正整数,所以下拉项里没有 0 和负数。
方案对比
| 场景 | 用哪个 demo | 关键属性 |
|---|---|---|
| 普通整数输入(0~100) | Demo 1 | editable、validator |
| 带单位的数值(如角度、百分比) | Demo 2 | textFromValue + valueFromText |
| 需要动态调整步长 | Demo 2 | stepSize 外部绑定 |
运行验证
- 用 Qt Creator 打开
qml_spinbox/CMakeLists.txt; - 按
Ctrl+R运行; - 左侧导航切换 demo,试试直接输入、加减按钮、切换步长。
扩展复用方向
- 把
°换成%、px、℃,就是不同场景的数值输入框,valueFromText里的替换字符跟着改。 - 想支持小数,把
IntValidator换成DoubleValidator就行。 - 步长随数值自动变化(数值大时步长也大)的话,可以在
onValueChanged里按当前值调整stepSize。
已验证环境:
- Qt 版本:Qt 6.8.2 / Qt 6.11.1
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_spinbox