DiagramDesigner/PropertyEditor/resources/Qml/ValueEditor/SizeFBox.qml

373 lines
11 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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