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,意思很直白:只能填整数,而且必须在 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 外部绑定

运行验证

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

扩展复用方向

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

已验证环境:

相关推荐
扶尔魔ocy21 小时前
【qt openGL入门笔记】windows编译MinGW版本的osgearth(2.10.1)
qt·opengl·osg
小王C语言1 天前
Qt常用控件:按钮类控件,普通按键、单选、复选
开发语言·qt
初阳7851 天前
【基于Qt5仿音乐播放器(六)】——细节打磨与总结
qt·1024程序员节
小鱼仙官2 天前
使用Qt封装C/C++ 动态库 用于第三方调用
c语言·c++·qt
扶尔魔ocy2 天前
【QT OpenGL】知识点编目及传送门
qt·opengl·osg
qq_401700412 天前
Qt Modbus 源码剖析:从 QModbusClient 到工业级通信框架
开发语言·qt·系统架构
GreenHandBruce2 天前
基于Qt 6.12.0 + FFmpeg 9.0.2的4k视频播放器
qt·ffmpeg·音视频
誰能久伴不乏2 天前
桌面客户端的运行日志系统:SQLite 分块 + 独立写线程 + 文本降级
数据库·c++·qt·架构·sqlite
沫璃染墨3 天前
《Qt从零入门系列(十五):Qt线程安全与锁机制详解——从QMutex到RAII与读写锁实战》
开发语言·c++·qt·安全·交互·线程·qt6.3
小豆庄3 天前
视频脱敏引擎的追踪难题:转场误判定、ID撞号和淡入窗口
qt·算法·目标检测·音视频·视频·敏捷流程