185 lines
5.1 KiB
QML
185 lines
5.1 KiB
QML
import QtQuick
|
||
import QtQuick.Controls
|
||
import QtQuick.Layouts
|
||
import QtQuick.Shapes
|
||
|
||
Item {
|
||
id: control
|
||
|
||
// 保持与框架一致的接口
|
||
property var value: false
|
||
property int decimals: 0
|
||
property string text: "Enabled"
|
||
property color textColor: "black"
|
||
property color checkedColor: "#2196F3"
|
||
property color uncheckedColor: "#cccccc"
|
||
property color checkedBoxColor: "white"
|
||
property color uncheckedBoxColor: "white"
|
||
property int boxSize: 16
|
||
property int spacing: 8
|
||
property int textSize: 12
|
||
property alias font: label.font
|
||
|
||
// 与框架一致的信号
|
||
signal asValueChanged(value: var)
|
||
signal boolValueChanged(bool checked) // 辅助信号,避免与内置信号冲突
|
||
|
||
implicitHeight: Math.max(boxSize, label.implicitHeight)
|
||
implicitWidth: boxSize + spacing + label.implicitWidth
|
||
|
||
function toggle() {
|
||
var newValue = !getBoolValue()
|
||
setValue(newValue)
|
||
}
|
||
|
||
function setValue(newValue) {
|
||
var boolValue = getBoolValue()
|
||
var newBoolValue = toBool(newValue)
|
||
|
||
if (boolValue !== newBoolValue) {
|
||
value = newBoolValue
|
||
boolValueChanged(newBoolValue)
|
||
asValueChanged(newBoolValue)
|
||
}
|
||
}
|
||
|
||
function getBoolValue() {
|
||
return toBool(value)
|
||
}
|
||
|
||
function toBool(value) {
|
||
if (typeof value === 'boolean') {
|
||
return value
|
||
} else if (typeof value === 'number') {
|
||
return value !== 0
|
||
} else if (typeof value === 'string') {
|
||
var str = value.toString().toLowerCase()
|
||
return str === 'true' || str === '1' || str === 'on'
|
||
}
|
||
return false
|
||
}
|
||
|
||
// 整个区域的点击事件
|
||
MouseArea {
|
||
anchors.fill: parent
|
||
|
||
onClicked: function(mouse) {
|
||
control.toggle()
|
||
mouse.accepted = true
|
||
}
|
||
}
|
||
|
||
RowLayout {
|
||
anchors.fill: parent
|
||
spacing: control.spacing
|
||
|
||
// 复选框
|
||
Rectangle {
|
||
id: checkBox
|
||
width: control.boxSize
|
||
height: control.boxSize
|
||
radius: 3
|
||
border.color: getBoolValue() ? control.checkedColor : control.uncheckedColor
|
||
border.width: 1
|
||
color: getBoolValue() ? control.checkedColor : control.uncheckedBoxColor
|
||
|
||
Layout.alignment: Qt.AlignVCenter
|
||
|
||
// 勾选标记
|
||
Shape {
|
||
anchors.centerIn: parent
|
||
width: 10
|
||
height: 8
|
||
visible: getBoolValue()
|
||
|
||
ShapePath {
|
||
strokeColor: "transparent"
|
||
fillColor: control.checkedBoxColor
|
||
strokeWidth: 0
|
||
|
||
PathMove { x: 0; y: 4 }
|
||
PathLine { x: 4; y: 8 }
|
||
PathLine { x: 10; y: 0 }
|
||
PathLine { x: 9; y: 0 }
|
||
PathLine { x: 4; y: 7 }
|
||
PathLine { x: 1; y: 4 }
|
||
}
|
||
}
|
||
|
||
// 悬停效果
|
||
Rectangle {
|
||
anchors.fill: parent
|
||
radius: parent.radius
|
||
color: "transparent"
|
||
border.color: "#888888"
|
||
border.width: boxMouseArea.containsMouse ? 1 : 0
|
||
opacity: boxMouseArea.containsMouse ? 0.3 : 0
|
||
}
|
||
|
||
// 复选框自身的点击事件
|
||
MouseArea {
|
||
id: boxMouseArea
|
||
anchors.fill: parent
|
||
hoverEnabled: true
|
||
|
||
onClicked: function(mouse) {
|
||
control.toggle()
|
||
mouse.accepted = true
|
||
}
|
||
}
|
||
}
|
||
|
||
// 标签文本
|
||
Label {
|
||
id: label
|
||
text: control.text
|
||
color: control.textColor
|
||
font.pixelSize: control.textSize
|
||
verticalAlignment: Text.AlignVCenter
|
||
|
||
Layout.alignment: Qt.AlignVCenter
|
||
Layout.fillWidth: true
|
||
|
||
// 鼠标悬停在文本上时的点击事件
|
||
MouseArea {
|
||
anchors.fill: parent
|
||
|
||
onClicked: function(mouse) {
|
||
control.toggle()
|
||
mouse.accepted = true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 键盘支持
|
||
Keys.onPressed: function(event) {
|
||
if (event.key === Qt.Key_Space || event.key === Qt.Key_Return) {
|
||
control.toggle()
|
||
event.accepted = true
|
||
}
|
||
}
|
||
|
||
// 聚焦支持
|
||
activeFocusOnTab: true
|
||
|
||
// 聚焦时的边框
|
||
Rectangle {
|
||
anchors.fill: parent
|
||
color: "transparent"
|
||
border.color: control.activeFocus ? "#2196F3" : "transparent"
|
||
border.width: 2
|
||
radius: 2
|
||
visible: control.activeFocus
|
||
}
|
||
|
||
// 当value从外部改变时,更新显示
|
||
onValueChanged: {
|
||
var boolValue = getBoolValue()
|
||
if (checkBox.border.color !== (boolValue ? control.checkedColor : control.uncheckedColor)) {
|
||
checkBox.border.color = boolValue ? control.checkedColor : control.uncheckedColor
|
||
checkBox.color = boolValue ? control.checkedColor : control.uncheckedBoxColor
|
||
}
|
||
}
|
||
}
|