2

我想在每个数字下都有一个带有小按钮的旋转框。根据选中的按钮,微调框的步长将相应调整。例如,如果选择小数点左侧的第一个按钮,则步长为 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
                    }
                }
            }
        }
    }
}
4

1 回答 1

2

您可以使用FontMetrics在 QML 中获取字体信息。如果您知道您正在使用的字体中的字符大小都差不多,则可以使用averageCharacterWidth,否则您可以将TextMetrics的boundingRect属性与字符串的每个单独字符一起使用。在这些类型的属性/功能方面有一些替代方案;检查文档。

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

要找到文本右对齐的位置,必须访问样式委托实例的大小(incrementControl / decrementControl )。这意味着您需要创建自己的SpinBoxStyle,以便您可以提供这些实例 ID,以便在其他地方访问它们。

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

于 2015-06-27T14:45:39.727 回答