QML之SpinBox

今天使用SpinBox,为了使界面风格统一,需要修改控件的边框颜色,文本颜色,点击时的背景颜色和文本颜色,这时需要对SpinBox作一定程度的定制化。

首先简单说明下SpinBox的参数:

  • displayText: 这是一个只读属性,表示SpinBox中显示的文本值。它等同于spinBox.textFromValue(spinBox.value, spinBox.locale)的结果。
  • editable: 这是一个布尔值,表示SpinBox是否可以编辑。如果设置为true,用户可以直接在SpinBox中输入数值。
  • down: 这是指向下指示器相关的属性组,包括:
    • down.hovered: 布尔值,表示鼠标是否悬停在向下指示器上。
    • down.implicitIndicatorHeight: 实数,定义向下指示器的高度。如果未设置,则使用隐式高度。
    • down.implicitIndicatorWidth: 实数,定义向下指示器的宽度。如果未设置,则使用隐式宽度。
    • down.indicator: Item类型,定义向下指示器的自定义元素。
    • down.pressed: 布尔值,表示向下指示器是否被按下。
  • up: 这是指向上指示器相关的属性组,包括:
    • up.hovered: 布尔值,表示鼠标是否悬停在向上指示器上。
    • up.implicitIndicatorHeight: 实数,定义向上指示器的高度。如果未设置,则使用隐式高度。
    • up.implicitIndicatorWidth: 实数,定义向上指示器的宽度。如果未设置,则使用隐式宽度。
    • up.indicator: Item类型,定义向上指示器的自定义元素。
    • up.pressed: 布尔值,表示向上指示器是否被按下。
  • from:起始值,默认是0
  • to:最大值,默认是99
  • stepSize:步长
  • textFromValue: 一个Javascript函数,用来把一个数字映射成一个字符串显示在界面上
  • valueFromText: 一个Javascript函数,作用和textFromValue相反

SpinBox主要有三部分组成:左右两个按钮,可以点击,中间一个文本框,用来显示数字或者其他文本。

左右两个按钮对应SpinBox的down.indicator和up.indicator参数,

文本框对应Control的contentItem参数.

弄清除了上面两条信息后,就可以开始自定这个控件了,唯一需要注意的是,左右两个按钮的大小需要设置正确,不然会显示不出来,这里需要用implicitHeight参数而不是height参数(宽度设置同理)。

继承标准的SpinBox,代码如下:

import QtQuick 2.15
import QtQuick.Controls 2.15

SpinBox {
    id:control
    width: 80
    height: 25

    property color border_color: "#B0E3F9"
    property color bkg_color: "#2C3E50"
    property color pressed_bkg_color: "#B0E3F9"
    property color txt_color:  "#B0E3F9"
    property color txt_sel_color:  "#2C3E50"

    background: Rectangle{
        border.width: 1
        border.color: border_color
        color: "transparent"
    }

    contentItem: TextInput{
            text: control.displayText
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
            overwriteMode: true
            selectByMouse: true
            color: txt_color
            selectionColor: txt_color
            selectedTextColor: bkg_color
        }

    down{
        indicator: Rectangle{
            x:0
            y:0
            implicitHeight: parent.height
            implicitWidth: parent.height
            color: control.down.pressed ? pressed_bkg_color : bkg_color
            border.width: 1
            border.color: txt_color
            Text{
                anchors.centerIn: parent
                text: "-"
                color: control.down.pressed ? bkg_color :txt_color
            }
        }
    }

    up{
        indicator: Rectangle{
            x:parent.width - width
            y:0
            implicitHeight: parent.height
            implicitWidth: parent.height
            color: control.up.pressed ? pressed_bkg_color : bkg_color
            border.width: 1
            border.color: txt_color
            Text{
                anchors.centerIn: parent
                text: "+"
                color: control.up.pressed ? bkg_color :txt_color
            }
        }
    }

}

使用Rectangle,InputBox, Timer的控件来模拟实现SpinbBox的功能,作为练习代码,功能也简单以下:

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts

Rectangle {
    id: control
    width: 80
    height: 30

    property int from: 0
    property int to: 100
    property int step: 1
    property int value: 22
    property color text_color: "#B0E3F9"

    border.width: 1
    border.color:  text_color
    color:"transparent"
    RowLayout{
        anchors.fill: parent
        spacing:0
        Rectangle{
            Layout.fillHeight: true
            Layout.margins: control.border.width
            Layout.preferredWidth: parent.height-2*control.border.width
            color:subMouseArea.containsPress ? Qt.darker(text_color, 2) : "transparent"
            Label{
                anchors.centerIn: parent
                text:"-"
                color: subMouseArea.containsPress ? Qt.lighter(text_color, 1.5) : text_color
            }
            MouseArea{
                id:subMouseArea
                anchors.fill: parent
                onClicked: {
                    control.value = control.value-1
                    if(control.value < control.from)
                        control.value = from;
                }
                onPressed: {
                    subTimer.start()
                }

                onReleased: {
                    subTimer.stop()
                    subTimer.interval = 200
                }
            }
        }
        Rectangle{
            Layout.fillHeight: true
            width: control.border.width
            color: text_color
        }
        TextInput{
            Layout.fillHeight: true
            Layout.fillWidth: true
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
            overwriteMode: true
            selectByMouse: true
            text: control.value
            color: text_color
            onAccepted: {
                if(isNaN(text)){
                    text = control.value
                }
                else{
                    control.value = text
                }
            }
        }
        Rectangle{
            Layout.fillHeight: true
            width: control.border.width
            color: text_color
        }
        Rectangle{
            Layout.fillHeight: true
            Layout.margins: control.border.width
            Layout.preferredWidth: parent.height-2*control.border.width
            color:addMouseArea.containsPress ? Qt.darker(text_color, 2) : "transparent"

            Label{
                anchors.centerIn: parent
                text:"+"
                color: addMouseArea.containsPress ? Qt.lighter(text_color, 1.5) : text_color
            }
            MouseArea{
                id: addMouseArea
                anchors.fill: parent

                onClicked: {
                    control.value = control.value+1
                    if(control.value > control.to)
                        control.value = control.to
                }

                onPressed: {
                    addTimer.start()
                }

                onReleased: {
                    addTimer.stop()
                    addTimer.interval = 200
                }
            }
        }
    }

    Timer{
        id: addTimer
        interval: 200
        repeat: true
        running: false
        onTriggered: {
            if(interval == 200)
                interval = 100
            control.value = control.value+1
            if(control.value > control.to)
                control.value = control.to
        }
    }

    Timer{
        id: subTimer
        interval: 200
        repeat: true
        running: false
        onTriggered: {
            if(interval == 200)
                interval = 100
            control.value = control.value-1
            if(control.value < control.from)
                control.value = control.from
        }
    }
}

下图中的两个SpinBox就是上面两种实现方式的效果:

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值