QML SpinBox 基础与步长控制:可编辑输入与自定义步长

写界面的时候,数字输入框是个躲不开的东西:调数值相关的活都绕不开它。这篇介绍 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,意思很直白:只能填整数,而且必须在 fromto 之间。手滑输了 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 跟着下拉框走。ComboBoxonCurrentTextChanged 接口里,把选中的文本转成数字赋给 spinBox.stepSize,选 "10" 后点一次加号就跳 10。注意 stepSize 只支持正整数,所以下拉项里没有 0 和负数。

方案对比

场景 用哪个 demo 关键属性
普通整数输入(0~100) Demo 1 editablevalidator
带单位的数值(如角度、百分比) Demo 2 textFromValue + valueFromText
需要动态调整步长 Demo 2 stepSize 外部绑定

运行验证

  1. 用 Qt Creator 打开 qml_spinbox/CMakeLists.txt
  2. Ctrl+R 运行;
  3. 左侧导航切换 demo,试试直接输入、加减按钮、切换步长。

扩展复用方向

  • ° 换成 %px,就是不同场景的数值输入框,valueFromText 里的替换字符跟着改。
  • 想支持小数,把 IntValidator 换成 DoubleValidator 就行。
  • 步长随数值自动变化(数值大时步长也大)的话,可以在 onValueChanged 里按当前值调整 stepSize

已验证环境

相关推荐
隐积3 小时前
Qt魔法之旅 · 全系列课程导航
qt
海清河晏1116 小时前
Qt 实战:信号与槽+事件系统
开发语言·c++·qt
郝学胜-神的一滴6 小时前
Qt 高级编程 037:QSS按钮样式封神指南
开发语言·c++·qt·软件工程·用户界面
only-lucky9 小时前
QML对话框控件
qt
郝学胜_神的一滴9 小时前
Qt 高级编程 038:打造高颜值下拉菜单按钮
c++·qt
小灰灰搞电子10 小时前
Qt 队列容器 QQueue 的详解与示例
开发语言·qt·qqueue
隐积10 小时前
3.1.8.Qt容器大家族(4):QByteArray——字节数组
开发语言·qt
xcyxiner1 天前
DicomViewer15(act验证ci)
qt