基于小数点的中心文本 QML 类型

Center Text QML type based on the dot of a decimal number

我有一个简单的 Text QML 类型:

Item {
    anchors.fill: parent

    Text {
        id: centerText
        text: "6.9"
        anchors.horizontalCenter: parent.horizontalCenter
        y: 570
    }
}

目前,Text 将基于字符串的整个长度居中。 但我想根据点字符将 Text 居中。

我正在考虑将实际的 Text 分成三部分:圆形部分、点和小数部分。但是我不认为我可以拆分 float 变量只得到小数部分。

有没有更方便更适配的方法QML

这是一个简单的示例,您可以如何实现这一点。 "dummy"隐藏文本用于衡量数字的整数部分有多宽,通过Math.floor()获得。然后你简单地定位它,使小数点总是在父对象的中心,不管数字是多少。

 Column {
    x: 100
    y: 200
    spacing: 5
    Slider {
      id: sl
      width: 400
      minimumValue: 0
      maximumValue: 100
    }
    Rectangle {
      width: 400
      height: 100
      Text {
        x: parent.width * .5 - dummy.width
        y: parent.height * .5 - height * .5
        text: sl.value
        Text {
          id: dummy
          text: Math.floor(sl.value)
          visible: false
        }
      }
    }
  }

顺便说一句,当你有 anchors.fill: parent 时,anchors.bottom: parent.bottom 是多余的。

您可能必须使用诸如基于 0 的填充之类的东西才能实现所需的对齐方式——或者找到一种 monospaced 字体,然后使用 spaces 而不是 0s

无论如何——这可能是一个解决方案:

import QtQuick 2.0


Item {
      height: 480
      width: 320
      /* list of float strings to pad */
      property var myFloats: ["6.9", "36.21", "4.632", "4225.2", "12.0"]
   

       /*  apply  zero-based padding to the strings on startup
           and output to the console */
      Component.onCompleted: {
           console.log(pad_floats());
      }

   
  /* function takes each decimal,and each integer separated by the .
      and figures out the length of the longest one, then uses
      a padding algorithm to add 0s to the start of the integers
      and 0s to the back of decimals and returns an array */
      function pad_floats() {
          var longest_int = 0;
          var longest_float = 0;
          var newFloats = [];
          for (var i = 0; i < myFloats.length; i++) {
              var tmp_float = myFloats[i];
              var tmp_int = tmp_float.split(".")[0]; // left side
              var tmp_dec = tmp_float.split(".")[1]; // right side

              /* check if either number is more digits than our longest one */
              if (tmp_int.length > longest_int) {
                    longest_int = tmp_int.length;
              }
              if (tmp_dec.length > longest_float) {
                    longest_float = tmp_dec.length;
              }

          }

          for (var u = 0; u < myFloats.length; u++) {
              var tmp_float = myFloats[u];
              var tmp_int = tmp_float.split(".")[0]; // left side of .
              var tmp_dec = tmp_float.split(".")[1]; // right side of .

              /* pad the two numbers */
              var new_int = pad(parseInt(tmp_int), longest_int, "0"); 
              var new_dec = pad(parseInt(tmp_dec), 0 - longest_float, "0");

              /* combine the new numbers back into one */
              var new_float = new_int + "." + new_dec;

              /* add to our array  to return */
              newFloats.push(new_float);

        }
        return newFloats;


  }

  function pad(n, width, z) {
       z = z || '0';
       n = n + '';
       return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
  }

   /*   Heres the ListView to show the actual list of floats */
  ListView {
       width: 320
       height: 480
       anchors.fill: parent
       anchors.left: parent.left
       model: pad_floats()  // our returned array from before
       delegate: listDelegate  // pointer to the Component below


  }

  Component {
      id: listDelegate
      Text {
          text: modelData
          font.pointSize: 11
          verticalAlignment: Text.AlignVCenter
          horizontalAlignment: Text.AlignHCenter
      }
  }

运行 此操作的结果是一个包含以下条目的 ListView:

0006.9
0036.21
0004.632
4225.2
0012.0

就是这样......就像我在答案顶部所说的那样 - 为了创建只有数字而没有额外 0 的预期结果,你必须使用具有相同的字体space 每个字符的数量,包括 (space) 字符。

这些通常称为 Monotype 或 Monospace 字体。

通常这些字体的名称会带有 "Mono" 字样,以便于查找。

找到合适的单字字体后,在 pad_floats() 函数中替换以下代码:

旧代码

      var new_int = pad(parseInt(tmp_int), longest_int, "0");
      var new_dec = pad(parseInt(tmp_dec), 0 - longest_float, "0");

新代码

      var new_int = pad(parseInt(tmp_int), longest_int, " ");
      var new_dec = pad(parseInt(tmp_dec), 0 - longest_float, " ");

注意到我是如何将最后一个“0”参数更改为“”的吗?最后一个字符串是填充字符串,因此您可以在其中放置任何内容,它会填充该字符串。

尽情享受吧。

编辑:最后我使用了ddriver的解决方案。如果您使用自定义字体,请不要忘记将其选项也包含在虚拟 Text 中!

我无法重现 ddriver 的解决方案。 我想出了自己的解决方案。我搜索了如何在 JavaScript 中获取浮点值的小数部分,发现了这个:

(4.89 + "").split(".")[1]; => 89

这比 C++ modf 函数更方便,因为它不返回“0”。部分。

多亏了这个,我只需要创建三个 Text QML 类型:

// Center horizontally number based on the dot
Text {
    id: testValueRoundPart
    anchors.right: testSpeedDot.left
    y: 570
    text:  (6.9 + "").split(".")[0]
}

Text {
    id: testSpeedDot
    y: 570
    text:  "."
    anchors.horizontalCenter: parent.horizontalCenter
}

Text {
    id: testSpeedValueDecimalPart
    y: 570
    anchors.left: testSpeedDot.right
    text: (6.9 + "").split(".")[1];
}

我一直在使用自定义字体(Sans-Guilt 和 Universalis;我不认为这些是 Monospace 字体)并且它有效。 它可能不是最优化的解决方案,但它符合我的需要。