import QtQuick import QtQuick.Controls import QtQuick.Layouts Item { id: control // 属性定义 property var value: Qt.size(0, 0) // QSizeF property int decimals: 1 // 默认小数位为1 property int precision: 2 // 精度,允许的小数位数 // 尺寸相关属性 property real minWidth: 0 property real maxWidth: 999999 property real minHeight: 0 property real maxHeight: 999999 // 步进增量 property real widthStep: 1.0 property real heightStep: 1.0 // 是否显示步进按钮 property bool showSpinButtons: true implicitHeight: 25 implicitWidth: showSpinButtons ? 140 : 120 // 信号 - 重命名避免与内置信号冲突 signal asValueChanged(value: var) signal sizeWidthChanged(width: real) // 改为 sizeWidthChanged signal sizeHeightChanged(height: real) // 改为 sizeHeightChanged // 获取宽高 function getWidth() { return value ? value.width : 0 } function getHeight() { return value ? value.height : 0 } // 设置值 function setValue(newValue: var) { if (!control.value || Math.abs(control.value.width - newValue.width) > 0.000001 || Math.abs(control.value.height - newValue.height) > 0.000001) { // 应用边界限制 var limitedWidth = Math.max(minWidth, Math.min(maxWidth, newValue.width)) var limitedHeight = Math.max(minHeight, Math.min(maxHeight, newValue.height)) // 保留精度 limitedWidth = parseFloat(limitedWidth.toFixed(precision)) limitedHeight = parseFloat(limitedHeight.toFixed(precision)) value = Qt.size(limitedWidth, limitedHeight) asValueChanged(value) } } // 设置宽度 function setWidth(width: real) { if (control.value && Math.abs(control.value.width - width) > 0.000001) { var limitedWidth = Math.max(minWidth, Math.min(maxWidth, width)) limitedWidth = parseFloat(limitedWidth.toFixed(precision)) control.setValue(Qt.size(limitedWidth, control.value.height)) } } // 设置高度 function setHeight(height: real) { if (control.value && Math.abs(control.value.height - height) > 0.000001) { var limitedHeight = Math.max(minHeight, Math.min(maxHeight, height)) limitedHeight = parseFloat(limitedHeight.toFixed(precision)) control.setValue(Qt.size(control.value.width, limitedHeight)) } } // 步进增加/减少 function stepWidth(positive: bool) { if (!control.value) return var step = positive ? widthStep : -widthStep setWidth(getWidth() + step) } function stepHeight(positive: bool) { if (!control.value) return var step = positive ? heightStep : -heightStep setHeight(getHeight() + step) } // UI布局 RowLayout { anchors.fill: parent spacing: 4 // 宽度部分 Label { text: "W:" Layout.alignment: Qt.AlignVCenter font.pixelSize: 10 } TextField { id: widthBox Layout.preferredWidth: 60 Layout.preferredHeight: 22 Layout.alignment: Qt.AlignVCenter selectByMouse: true // 允许鼠标选择文本 text: control.value ? control.value.width.toFixed(control.decimals) : "0.0" font.pixelSize: 10 leftPadding: 4 rightPadding: 4 // 双击全选的处理 MouseArea { id: widthMouseArea anchors.fill: parent propagateComposedEvents: true acceptedButtons: Qt.LeftButton cursorShape: Qt.IBeamCursor onDoubleClicked: function(mouse) { parent.selectAll() parent.forceActiveFocus() mouse.accepted = true } onClicked: function(mouse) { // 单击时设置焦点但不全选 parent.forceActiveFocus() mouse.accepted = false } } onActiveFocusChanged: { if (activeFocus) { // 如果不是双击触发的焦点变化,就全选文本 if (!widthMouseArea.containsPress) { selectAll() } } } // 验证器 validator: DoubleValidator { bottom: control.minWidth top: control.maxWidth decimals: control.precision notation: DoubleValidator.StandardNotation } background: Rectangle { color: widthBox.enabled ? "white" : "#f0f0f0" border.color: widthBox.activeFocus ? "#2196F3" : "#cccccc" border.width: 1 radius: 2 } onEditingFinished: { var num = parseFloat(text) if (!isNaN(num) && control.value) { control.setWidth(num) } else { // 恢复原值 widthBox.text = control.value ? control.value.width.toFixed(control.decimals) : "0.0" } } // 键盘上下键调整 Keys.onUpPressed: function(event) { control.stepWidth(true) event.accepted = true } Keys.onDownPressed: function(event) { control.stepWidth(false) event.accepted = true } } // 宽度步进按钮 Row { visible: control.showSpinButtons spacing: 0 Layout.alignment: Qt.AlignVCenter Button { width: 12 height: 11 text: "▲" font.pixelSize: 6 padding: 0 onClicked: control.stepWidth(true) background: Rectangle { color: parent.hovered ? "#e0e0e0" : "transparent" border.color: "#cccccc" border.width: 1 radius: 2 } } Button { width: 12 height: 11 text: "▼" font.pixelSize: 6 padding: 0 onClicked: control.stepWidth(false) background: Rectangle { color: parent.hovered ? "#e0e0e0" : "transparent" border.color: "#cccccc" border.width: 1 radius: 2 } } } // 高度部分 Label { text: "H:" Layout.alignment: Qt.AlignVCenter font.pixelSize: 10 } TextField { id: heightBox Layout.preferredWidth: 60 Layout.preferredHeight: 22 Layout.alignment: Qt.AlignVCenter selectByMouse: true // 允许鼠标选择文本 text: control.value ? control.value.height.toFixed(control.decimals) : "0.0" font.pixelSize: 10 leftPadding: 4 rightPadding: 4 // 双击全选的处理 MouseArea { id: heightMouseArea anchors.fill: parent propagateComposedEvents: true acceptedButtons: Qt.LeftButton cursorShape: Qt.IBeamCursor onDoubleClicked: function(mouse) { parent.selectAll() parent.forceActiveFocus() mouse.accepted = true } onClicked: function(mouse) { // 单击时设置焦点但不全选 parent.forceActiveFocus() mouse.accepted = false } } onActiveFocusChanged: { if (activeFocus) { // 如果不是双击触发的焦点变化,就全选文本 if (!heightMouseArea.containsPress) { selectAll() } } } // 验证器 validator: DoubleValidator { bottom: control.minHeight top: control.maxHeight decimals: control.precision notation: DoubleValidator.StandardNotation } background: Rectangle { color: heightBox.enabled ? "white" : "#f0f0f0" border.color: heightBox.activeFocus ? "#2196F3" : "#cccccc" border.width: 1 radius: 2 } onEditingFinished: { var num = parseFloat(text) if (!isNaN(num) && control.value) { control.setHeight(num) } else { // 恢复原值 heightBox.text = control.value ? control.value.height.toFixed(control.decimals) : "0.0" } } // 键盘上下键调整 Keys.onUpPressed: function(event) { control.stepHeight(true) event.accepted = true } Keys.onDownPressed: function(event) { control.stepHeight(false) event.accepted = true } } // 高度步进按钮 Row { visible: control.showSpinButtons spacing: 0 Layout.alignment: Qt.AlignVCenter Button { width: 12 height: 11 text: "▲" font.pixelSize: 6 padding: 0 onClicked: control.stepHeight(true) background: Rectangle { color: parent.hovered ? "#e0e0e0" : "transparent" border.color: "#cccccc" border.width: 1 radius: 2 } } Button { width: 12 height: 11 text: "▼" font.pixelSize: 6 padding: 0 onClicked: control.stepHeight(false) background: Rectangle { color: parent.hovered ? "#e0e0e0" : "transparent" border.color: "#cccccc" border.width: 1 radius: 2 } } } Item { Layout.fillWidth: true } } // 当value从外部改变时,更新输入框显示 onValueChanged: { if (value) { if (!widthBox.activeFocus) { widthBox.text = value.width.toFixed(decimals) } if (!heightBox.activeFocus) { heightBox.text = value.height.toFixed(decimals) } // 发出单独的宽高变化信号 sizeWidthChanged(value.width) sizeHeightChanged(value.height) } } }