旋转箱号下的QtQuick按钮

时间:2015-06-27 12:12:31

标签: qml qtquick2 qspinbox

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

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

enter image description here

下一步是调整按钮的大小和位置,使它们直接在相应的数字位置下排列。在非常低的级别,这将涉及获取字体细节,确定每个数字的大小和位置,然后相应地调整和定位按钮。这是我能在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
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您可以使用FontMetrics在QML中获取字体信息。如果您知道自己使用的字体中的字符大小相同,则可以使用averageCharacterWidth,否则您可以使用boundingRectTextMetrics属性字符串的个别字符。在这些类型的属性/功能方面有一些替代方案;查看文档。

您可能需要增加pixelSize中使用的fontletterSpacingSpinBox,因为它们默认情况下非常接近,不会给单选按钮留下很大的空间。

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

然而,控件无法满足每个问题,而且这个问题非常具体。此时,创建自己的DecimalSpinBox组件可能更容易。然后,您可以完全控制字符和单选按钮的位置。一旦你创建了自己的风格(上面提到的上述方法),你就会失去原生风格。