【写在前面】
在做编辑相关的应用经常会用到颜色选择器。
实际上, Qt Widgets 时代使用 QColorDialog 或者 Qml 中 ColorDialog 即可完成一般的颜色选择的需求。
然鹅现在都 Windows 11了!!还在用那么拉跨的东西,实在是看不下去了。
然后自己一直很喜欢用 Windows 画图3D的那个颜色选择器,因此我决定仿照实现一个,并且还为它增加了一个透明度。
【正文开始】
不多bb,先直接看效果图,喜欢的话接着往下看~
首先,需要实现一个渐变的面板,这里用了一点小小的技巧。
底层用 白色=>当前颜色的渐变(左到右),上层用纯透明=>纯不透明黑色的渐变(上到下),然后他们混合起来就是我们一般见到的渐变面板。
Rectangle {
x: pickerRect.cursorWidth * 0.5
y: pickerRect.height - pickerRect.cursorWidth * 0.5
width: pickerRect.height - pickerRect.cursorWidth
height: pickerRect.width - pickerRect.cursorWidth
rotation: -90
transformOrigin: Item.TopLeft
gradient: Gradient {
GradientStop { position: 0.0; color: "white" }
GradientStop { position: 1.0; color: pickerRect.hueColor }
}
}
Rectangle {
x: pickerRect.cursorWidth * 0.5
y: pickerRect.cursorWidth * 0.5
width: pickerRect.width - pickerRect.cursorWidth
height: pickerRect.height - pickerRect.cursorWidth
gradient: Gradient {
GradientStop { position: 1.0; color: "#ff000000" }
GradientStop { position: 0.0; color: "#00000000" }
}
}
接着,现在要实现一个 hue 的颜色选择条带:
Rectangle {
id: huePicker
width: pickerRect.width - pickerRect.cursorWidth
height: 32
anchors.top: pickerRect.bottom
anchors.topMargin: 10
anchors.left: contentText.left
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: "#ff0000" }
GradientStop { position: 0.16; color: "#ffff00" }
GradientStop { position: 0.33; color: "#00ff00" }
GradientStop { position: 0.5; color: "#00ffff" }
GradientStop { position: 0.76; color: "#0000ff" }
GradientStop { position: 0.85; color: "#ff00ff" }
GradientStop { position: 1.0; color: "#ff0000" }
}
Rectangle {
id: hueSlider
width: height
height: parent.height
anchors.verticalCenter: parent.verticalCenter
border.color: "#e6e6e6"
border.width: 2
scale: 0.9
color: pickerRect.hueColor
property real value: x / (parent.width - width)
Behavior on scale { NumberAnimation { easing.type: Easing.OutBack; duration: 300 } }
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: "transparent"
border.color: "white"
border.width: 2
}
}
MouseArea {
anchors.fill: parent
function handleCursorPos(x) {
let halfWidth = hueSlider.width * 0.5;
hueSlider.x = Math.max(0, Math.min(width, x + halfWidth) - hueSlider.width);
}
onPressed: (mouse) => {
hueSlider.scale = 0.6;
handleCursorPos(mouse.x);
}
onReleased: hueSlider.scale = 0.9;
onPositionChanged: (mouse) => handleCursorPos(mouse.x);
}
}
渐变条带比较简单,精确控制好渐变位置即可,然后增加了一个选择的方块,用于判断和选择位置。
接着我们要增加一个透明度选择条带,这里我们先生成一些黑白相间的格子作为底层,然后在上面放上透明=>不透明的条带即可:
Item {
id: alphaPickerItem
width: huePicker.width
height: huePicker.height
anchors.top: huePicker.bottom
anchors.topMargin: 25
anchors.left: huePicker.left
Grid {
id: alphaPicker
anchors.fill: parent
rows: 4
columns: 29
clip: true
property real cellWidth: width / columns
property real cellHeight: height / rows
Repeater {
model: parent.columns * parent.rows
Rectangle {
width: alphaPicker.cellWidth
height: width
color: (index % 2 == 0) ? "gray" : "transparent"
}
}
}
Rectangle {
anchors.fill: parent
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 1.0; color: "#ff000000" }
GradientStop { position: 0.0; color: "#00ffffff" }
}
}
Rectangle {
id: alphaSlider
x: parent.width - width
width: height
height: parent.height
anchors.verticalCenter: parent.verticalCenter
color: Qt.rgba(0.1, 0.1, 0.1, (value + 1.0) / 2.0)
border.color: "#e6e6e6"
border.width: 2
scale: 0.9
property real value: x / (parent.width - width)
Behavior on scale { NumberAnimation { easing.type: Easing.OutBack; duration: 300 } }
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: "transparent"
border.color: "white"
border.width: 1
}
}
MouseArea {
anchors.fill: parent
function handleCursorPos(x) {
let halfWidth = alphaSlider.width * 0.5;
alphaSlider.x = Math.max(0, Math.min(width, x + halfWidth) - alphaSlider.width);
}
onPressed: (mouse) => {
alphaSlider.scale = 0.6;
handleCursorPos(mouse.x);
}
onReleased: alphaSlider.scale = 0.9;
onPositionChanged: (mouse) => handleCursorPos(mouse.x);
}
}
和渐变条带一致,这里也放置了一个选择框。
到这里,比较重要的部分就讲完了,不过我要提示一些 Qml 的小技巧:
Qml color 类型有一些很好用的属性,例如:hsvHue、hsvSaturation、hsvValue、hslHue、 hslSaturation、 hslLightness,这些属性在实现颜色相关控件时非常有用。
最后还有一些其他零碎的代码,例如编辑框,过渡动画等等就不再赘述了,自行下载源码编辑测试即可。
【结语】
一开始我实现的 ColorPicker 只是一个 Rectangle 中,然鹅很多时候也需要弹窗形式的,所以又增加了一个 ColorPickerPopup ,直接下载源码就可以获得了(多多star呀..⭐_⭐):。
Github的:GitHub - mengps/QmlControls: Qt / Qml 控件Qt / Qml 控件. Contribute to mengps/QmlControls development by creating an account on GitHub.https://github.com/mengps/QmlControls CSDN的:https://download.csdn.net/download/u011283226/86995876https://download.csdn.net/download/u011283226/86995876