微调框数字下的 QtQuick 按钮

QtQuick buttons under spinbox numbers

我想要一个旋转框,每个数字下面都有小按钮。根据选中的按钮,旋转框的步长将相应调整。例如,如果选择小数点左边的第一个按钮,则步长为 1,如果选择小数点右边的第一个按钮,则步长为 0.1。

我已经弄清楚如何获得我想要的所有行为,并且我已经将旋转框与适当的按钮组合在一起。

下一步是调整按钮的大小和位置,使它们直接排列在相应的数字位置下方。在非常低的级别上,这将涉及获取字体详细信息、确定每个数字的大小和位置,然后相应地调整按钮的大小和位置。这是我可以在 qml 中实现的吗?

这是上面按钮的 qml:

import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1

Item {
    id: root
    property int decimalsLeft: 2
    property int decimalsRight: 3
    property alias maximumValue: spinBox.maximumValue
    property alias minimumValue: spinBox.minimumValue
    property alias value: spinBox.value

    width: layout.width
    height: layout.height

    ColumnLayout {
        id: layout

        SpinBox {
            id: spinBox
            Layout.fillWidth: true
            width: parent.width
            decimals: root.decimalsRight
            horizontalAlignment: Qt.AlignRight
            maximumValue: 1e3
            minimumValue: -1e3
        }

        // Make row of buttons under number to select
        // step size
        ExclusiveGroup {id: decimalSelector}
        RowLayout{
            Repeater {
                id: rdButtons
                RadioButton {
                    exclusiveGroup: decimalSelector
                    onCheckedChanged: {
                        if(!checked) {
                            return
                        }

                        var relIndex = decimalsLeft-index-1
                        if(relIndex == -1) {// decimal location so don't do anything
                            return
                        }

                        if(relIndex < 0) {
                            relIndex += 1
                        }

                        spinBox.stepSize = Math.pow(10, relIndex)
                    }
                }

                onModelChanged: {
                    for(var i=0; i<rdButtons.count; i++) {
                        rdButtons.itemAt(i).enabled = true
                    }

                    // disable selector associated with the decimal point
                    if(rdButtons.count > decimalsLeft) {
                        rdButtons.itemAt(decimalsLeft).enabled = false
                    }

                    // now find which selector matches our current step size
                    var log = Math.round(Math.log(spinBox.stepSize) / Math.LN10)
                    var idx = -1
                    if(log >= 0) {
                        idx = decimalsLeft-log-1
                    }
                    else {
                        idx = decimalsLeft-log
                    }

                    // an finally apply the selection
                    if(rdButtons.count == 0) {
                        return
                    }
                    else if(idx < 0) {
                        rdButtons.itemAt(0).checked = true
                    }
                    else if(idx >= rdButtons.count) {
                        if(idx == decimalsLeft+1) {
                            rdButtons.itemAt(rdButtons.count-2).checked = true
                        }
                        else {
                            rdButtons.itemAt(rdButtons.count-1).checked = true
                        }
                    }
                    else {
                        rdButtons.itemAt(idx).checked = true
                    }
                }

                model: decimalsLeft + decimalsRight + 1

                Component.onCompleted: {
                    if(decimalsLeft < rdButtons.count) {
                        rdButtons.itemAt(decimalsLeft).enabled = false
                    }
                    if(decimalsLeft > 0) {
                        rdButtons.itemAt(decimalsLeft-1).checked = true
                    }
                }
            }
        }
    }
}

您可以使用 FontMetrics. If you know that the characters in the font you're using are all around the same size, you can use averageCharacterWidth, otherwise you can use the boundingRect property of TextMetrics 在 QML 中获取字符串的每个单独字符的字体信息。在这些类型中,properties/functions 有一些替代方案;查看文档。

您可能需要增加 SpinBox 中使用的 fontpixelSizeletterSpacing,因为它们在默认情况下非常靠近,这不会给单选按钮留下太多空间。

访问样式委托实例的大小(incrementControl/decrementControl) will be necessary to find the position at which the text is right aligned. This means you'll need to create your own SpinBoxStyle 以便您可以为这些实例提供 ID,以便在其他地方访问它们。

但是,控件无法解决所有问题,而这个问题非常具体。此时,创建自己的 DecimalSpinBox 组件可能会更容易。然后您可以完全控制字符和单选按钮的位置。一旦您创建了自己的样式(上面提到的以前的方法),您无论如何都会失去原生样式。