我希望每个数字下都有一个带有小按钮的旋转框。根据选中的按钮,旋转框的步长将根据需要进行调整。例如,如果选择小数点左边的第一个按钮,则步长为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
}
}
}
}
}
}
答案 0 :(得分:2)
您可以使用FontMetrics在QML中获取字体信息。如果您知道自己使用的字体中的字符大小相同,则可以使用averageCharacterWidth,否则您可以使用boundingRect的TextMetrics属性字符串的个别字符。在这些类型的属性/功能方面有一些替代方案;查看文档。
您可能需要增加pixelSize
中使用的font的letterSpacing
和SpinBox
,因为它们默认情况下非常接近,不会给单选按钮留下很大的空间。
有必要访问样式委托实例(incrementControl / decrementControl)的大小,以找到文本右对齐的位置。这意味着您需要创建自己的SpinBoxStyle,以便您可以提供这些实例ID,以便在其他位置访问它们。
然而,控件无法满足每个问题,而且这个问题非常具体。此时,创建自己的DecimalSpinBox
组件可能更容易。然后,您可以完全控制字符和单选按钮的位置。一旦你创建了自己的风格(上面提到的上述方法),你就会失去原生风格。