2015-06-27 19 views
2

我想在每个编号下都有一个带有小按钮的旋转框。根据选中的按钮,旋转框的步长将根据调整。例如,如果选择了小数点左边的第一个按钮,则步长为1,如果选择了小数点第一个按钮右边,则步长为0.1。旋转编号下的Qt快速按钮

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

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 
        } 
       } 
      } 
     } 
    } 
} 

回答

2

你可以得到的字体信息,QML与FontMetrics。如果您知道所用字体中的字符大小相同,则可以使用averageCharacterWidth,否则可以使用TextMetricsboundingRect属性与字符串的每个单独字符。在这些类型的属性/功能方面有几种选择;检查文档。

你可能会需要增加在SpinBox使用的fontpixelSizeletterSpacing,因为他们是相当并拢默认情况下,它不会太多空间留给单选按钮。

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

但是,控制不能满足所有问题,而且这个问题很具体。在这一点上,创建您自己的DecimalSpinBox组件可能会更容易。然后您可以完全控制角色和单选按钮的位置。只要你创建你自己的风格(上面提到的以前的方法),无论如何你都会失去本地风格。

+0

你知道我该怎么去查询第一个字符的位置(或者一些代理让我足够接近)?是否有可能找到up/dn箭头按钮的大小?那么我可以从右边那边抵消那个数额加上边际。 – ryan0270

+0

对不起,我忘了那部分。我已经更新了我的答案。 – Mitch