基于小数点的中心文本 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 字体)并且它有效。
它可能不是最优化的解决方案,但它符合我的需要。
我有一个简单的 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 字体)并且它有效。 它可能不是最优化的解决方案,但它符合我的需要。