diff --git a/example/T_CalendarPicker.qml b/example/T_CalendarPicker.qml
index 26c6044d..0540f62c 100644
--- a/example/T_CalendarPicker.qml
+++ b/example/T_CalendarPicker.qml
@@ -8,26 +8,29 @@ FluScrollablePage{
title:"CalendarPicker"
+ FluArea{
+ width: parent.width
+ Layout.topMargin: 20
+ height: 350
+ paddings: 1
+ FluCalendarView{
+
+ }
+ }
FluArea{
width: parent.width
Layout.topMargin: 20
height: 80
paddings: 10
-
ColumnLayout{
-
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
-
FluCalendarPicker{
}
-
}
}
-
-
}
diff --git a/example/T_Carousel.qml b/example/T_Carousel.qml
deleted file mode 100644
index 8358a4fb..00000000
--- a/example/T_Carousel.qml
+++ /dev/null
@@ -1,36 +0,0 @@
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import QtQuick.Window 2.15
-import QtQuick.Controls 2.15
-import QtGraphicalEffects 1.15
-import FluentUI 1.0
-
-FluScrollablePage{
-
- title:"Carousel"
-
- FluArea{
- width: parent.width
- height: 370
- paddings: 10
- Layout.topMargin: 20
- Column{
- spacing: 15
- anchors{
- verticalCenter: parent.verticalCenter
- left:parent.left
- }
- FluText{
- text:"轮播图,支持无限轮播,无限滑动,用ListView实现的组件"
- }
- FluCarousel{
- id:carousel
- Layout.topMargin: 20
- Layout.leftMargin: 5
- Component.onCompleted: {
- carousel.setData([{url:"qrc:/res/image/banner_1.jpg"},{url:"qrc:/res/image/banner_2.jpg"},{url:"qrc:/res/image/banner_3.jpg"}])
- }
- }
- }
- }
-}
diff --git a/example/T_ColorPicker.qml b/example/T_ColorPicker.qml
new file mode 100644
index 00000000..1ba0aa78
--- /dev/null
+++ b/example/T_ColorPicker.qml
@@ -0,0 +1,57 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Window 2.15
+import QtGraphicalEffects 1.15
+import FluentUI 1.0
+
+FluScrollablePage{
+
+ title:"ColorPicker"
+
+ FluArea{
+ width: parent.width
+ height: 280
+ Layout.topMargin: 20
+ paddings: 10
+ ColumnLayout{
+ anchors{
+ verticalCenter: parent.verticalCenter
+ left:parent.left
+ }
+ FluText{
+ text:"此颜色组件是Github上大佬封装的"
+ }
+ FluTextButton{
+ leftPadding: 0
+ rightPadding: 0
+ text:"https://github.com/rshest/qml-colorpicker"
+ onClicked: {
+ Qt.openUrlExternally(text)
+ }
+ }
+ FluColorView{
+
+ }
+ }
+ }
+
+ FluArea{
+ width: parent.width
+ Layout.topMargin: 20
+ height: 60
+ paddings: 10
+
+ RowLayout{
+ FluText{
+ text:"点击选择颜色->"
+ Layout.alignment: Qt.AlignVCenter
+ }
+ FluColorPicker{
+
+ }
+ }
+ }
+
+}
+
diff --git a/example/page/AboutPage.qml b/example/page/AboutPage.qml
index cde73107..235300b1 100644
--- a/example/page/AboutPage.qml
+++ b/example/page/AboutPage.qml
@@ -35,7 +35,7 @@ FluWindow {
fontStyle: FluText.Title
}
FluText{
- text:"v1.1.2"
+ text:"v1.1.3"
fontStyle: FluText.Body
Layout.alignment: Qt.AlignBottom
}
diff --git a/example/page/MainPage.qml b/example/page/MainPage.qml
index fcd7bc28..f9c9c334 100644
--- a/example/page/MainPage.qml
+++ b/example/page/MainPage.qml
@@ -79,6 +79,13 @@ FluWindow {
}
}
+ FluPaneItem{
+ title:"ColorPicker"
+ onTap:{
+ nav_view.push("qrc:/T_ColorPicker.qml")
+ }
+ }
+
FluPaneItemHeader{
title:"Surface"
}
@@ -97,13 +104,6 @@ FluWindow {
}
}
- FluPaneItem{
- title:"Calendar"
- onTap:{
- nav_view.push("qrc:/T_Calendar.qml")
- }
- }
-
FluPaneItem{
title:"Badge"
onTap:{
diff --git a/example/qml.qrc b/example/qml.qrc
index bdb97871..93fa8550 100644
--- a/example/qml.qrc
+++ b/example/qml.qrc
@@ -34,7 +34,6 @@
T_DatePicker.qml
T_MultiWindow.qml
T_Menu.qml
- T_Carousel.qml
res/image/banner_1.jpg
res/image/banner_2.jpg
res/image/banner_3.jpg
@@ -44,5 +43,6 @@
T_Badge.qml
T_Calendar.qml
T_CalendarPicker.qml
+ T_ColorPicker.qml
diff --git a/src/Fluent.cpp b/src/Fluent.cpp
index bd347ac2..4c8af0e4 100644
--- a/src/Fluent.cpp
+++ b/src/Fluent.cpp
@@ -47,6 +47,8 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCalendarView.qml"),uri,major,minor,"FluCalendarView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluDatePicker.qml"),uri,major,minor,"FluDatePicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTimePicker.qml"),uri,major,minor,"FluTimePicker");
+ qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluColorView.qml"),uri,major,minor,"FluColorView");
+ qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluColorPicker.qml"),uri,major,minor,"FluColorPicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCarousel.qml"),uri,major,minor,"FluCarousel");
diff --git a/src/colorpicker/ColorPicker.qml b/src/colorpicker/ColorPicker.qml
new file mode 100644
index 00000000..b86308e4
--- /dev/null
+++ b/src/colorpicker/ColorPicker.qml
@@ -0,0 +1,234 @@
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Controls 2.15
+import "content"
+
+Rectangle {
+ id: colorPicker
+ property color colorValue: "transparent"
+ property bool enableAlphaChannel: true
+ property bool enableDetails: true
+ property int colorHandleRadius : 8
+ property color _changingColorValue : _hsla(hueSlider.value, sbPicker.saturation,sbPicker.brightness, alphaSlider.value)
+ on_ChangingColorValueChanged: {
+ colorValue = _changingColorValue
+ }
+
+ signal colorChanged(color changedColor)
+
+ implicitWidth: picker.implicitWidth
+ implicitHeight: picker.implicitHeight
+ color: "#00000000"
+ clip: true
+
+
+ RowLayout {
+ id: picker
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: colorHandleRadius
+ anchors.bottom: parent.bottom
+ spacing: 0
+
+
+ SBPicker {
+ id: sbPicker
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.minimumWidth: 200
+ Layout.minimumHeight: 200
+ hueColor: {
+ var v = 1.0-hueSlider.value
+ if(0.0 <= v && v < 0.16) {
+ return Qt.rgba(1.0, 0.0, v/0.16, 1.0)
+ } else if(0.16 <= v && v < 0.33) {
+ return Qt.rgba(1.0 - (v-0.16)/0.17, 0.0, 1.0, 1.0)
+ } else if(0.33 <= v && v < 0.5) {
+ return Qt.rgba(0.0, ((v-0.33)/0.17), 1.0, 1.0)
+ } else if(0.5 <= v && v < 0.76) {
+ return Qt.rgba(0.0, 1.0, 1.0 - (v-0.5)/0.26, 1.0)
+ } else if(0.76 <= v && v < 0.85) {
+ return Qt.rgba((v-0.76)/0.09, 1.0, 0.0, 1.0)
+ } else if(0.85 <= v && v <= 1.0) {
+ return Qt.rgba(1.0, 1.0 - (v-0.85)/0.15, 0.0, 1.0)
+ } else {
+ return "red"
+ }
+ }
+ }
+
+ Item {
+ id: huePicker
+ width: 12
+ Layout.fillHeight: true
+ Layout.topMargin: colorHandleRadius
+ Layout.bottomMargin: colorHandleRadius
+
+ Rectangle {
+ anchors.fill: parent
+ id: colorBar
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "#FF0000" }
+ GradientStop { position: 0.85; color: "#FFFF00" }
+ GradientStop { position: 0.76; color: "#00FF00" }
+ GradientStop { position: 0.5; color: "#00FFFF" }
+ GradientStop { position: 0.33; color: "#0000FF" }
+ GradientStop { position: 0.16; color: "#FF00FF" }
+ GradientStop { position: 0.0; color: "#FF0000" }
+ }
+ }
+ ColorSlider {
+ id: hueSlider; anchors.fill: parent
+ }
+ }
+
+ Item {
+ id: alphaPicker
+ visible: enableAlphaChannel
+ width: 12
+ Layout.leftMargin: 4
+ Layout.fillHeight: true
+ Layout.topMargin: colorHandleRadius
+ Layout.bottomMargin: colorHandleRadius
+ Checkerboard { cellSide: 4 }
+ Rectangle {
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#FF000000" }
+ GradientStop { position: 1.0; color: "#00000000" }
+ }
+ }
+ ColorSlider {
+ id: alphaSlider; anchors.fill: parent
+ }
+ }
+
+ Column {
+ id: detailColumn
+ Layout.leftMargin: 4
+ Layout.fillHeight: true
+ Layout.topMargin: colorHandleRadius
+ Layout.bottomMargin: colorHandleRadius
+ Layout.alignment: Qt.AlignRight
+ visible: enableDetails
+
+ PanelBorder {
+ width: parent.width
+ height: 30
+ visible: enableAlphaChannel
+ Checkerboard { cellSide: 5 }
+ Rectangle {
+ width: parent.width; height: 30
+ border.width: 1; border.color: "black"
+ color: colorPicker.colorValue
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: 1
+ }
+
+
+ PanelBorder {
+ id: colorEditBox
+ height: 15; width: parent.width
+ TextInput {
+ anchors.fill: parent
+ color: "#AAAAAA"
+ selectionColor: "#FF7777AA"
+ font.pixelSize: 11
+ maximumLength: 9
+ focus: false
+ text: _fullColorString(colorPicker.colorValue, alphaSlider.value)
+ selectByMouse: true
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: 8
+ }
+
+ Column {
+ width: parent.width
+ spacing: 1
+ NumberBox { caption: "H:"; value: hueSlider.value.toFixed(2) }
+ NumberBox { caption: "S:"; value: sbPicker.saturation.toFixed(2) }
+ NumberBox { caption: "B:"; value: sbPicker.brightness.toFixed(2) }
+ }
+
+ Item {
+ width: parent.width
+ height: 8
+ }
+
+ Column {
+ width: parent.width
+ spacing: 1
+ NumberBox {
+ caption: "R:"
+ value: _getChannelStr(colorPicker.colorValue, 0)
+ min: 0; max: 255
+ }
+ NumberBox {
+ caption: "G:"
+ value: _getChannelStr(colorPicker.colorValue, 1)
+ min: 0; max: 255
+ }
+ NumberBox {
+ caption: "B:"
+ value: _getChannelStr(colorPicker.colorValue, 2)
+ min: 0; max: 255
+ }
+ }
+
+ Item{
+ width: parent.width
+ height: 1
+ }
+
+ NumberBox {
+ visible: enableAlphaChannel
+ caption: "A:"; value: Math.ceil(alphaSlider.value*255)
+ min: 0; max: 255
+ }
+ }
+ }
+
+ function _hsla(h, s, b, a) {
+ var lightness = (2 - s)*b
+ var satHSL = s*b/((lightness <= 1) ? lightness : 2 - lightness)
+ lightness /= 2
+
+ var c = Qt.hsla(h, satHSL, lightness, a)
+
+ colorChanged(c)
+
+ return c
+ }
+
+ function _rgb(rgb, a) {
+
+ var c = Qt.rgba(rgb.r, rgb.g, rgb.b, a)
+
+ colorChanged(c)
+
+ return c
+ }
+
+ function _fullColorString(clr, a) {
+ return "#" + ((Math.ceil(a*255) + 256).toString(16).substr(1, 2) + clr.toString().substr(1, 6)).toUpperCase()
+ }
+
+ function _getChannelStr(clr, channelIdx) {
+ return parseInt(clr.toString().substr(channelIdx*2 + 1, 2), 16)
+ }
+
+ function setColor(color) {
+ var c = Qt.tint(color, "transparent")
+ alphaSlider.setValue(c.a)
+ colorPicker.colorValue = c
+ }
+}
diff --git a/src/colorpicker/content/Checkerboard.qml b/src/colorpicker/content/Checkerboard.qml
new file mode 100644
index 00000000..81f713a1
--- /dev/null
+++ b/src/colorpicker/content/Checkerboard.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.15
+Grid {
+ id: root
+ property int cellSide: 5
+ anchors.fill: parent
+ rows: height/cellSide; columns: width/cellSide
+ clip: true
+ Repeater {
+ model: root.columns*root.rows
+ Rectangle {
+ width: root.cellSide; height: root.cellSide
+ color: (index%2 == 0) ? "gray" : "white"
+ }
+ }
+}
+
diff --git a/src/colorpicker/content/ColorSlider.qml b/src/colorpicker/content/ColorSlider.qml
new file mode 100644
index 00000000..c7262f15
--- /dev/null
+++ b/src/colorpicker/content/ColorSlider.qml
@@ -0,0 +1,43 @@
+import QtQuick 2.15
+
+Item {
+ property int cursorHeight: 7
+ property real value: (1 - pickerCursor.y/height)
+ width: 15
+ height: 300
+ Item {
+ id: pickerCursor
+ width: parent.width
+ Rectangle {
+ x: -3; y: -height*0.5
+ width: parent.width + 4; height: cursorHeight
+ border.color: "black"; border.width: 1
+ color: "transparent"
+ Rectangle {
+ anchors.fill: parent; anchors.margins: 2
+ border.color: "white"; border.width: 1
+ color: "transparent"
+ }
+ }
+ }
+ MouseArea {
+ y: -Math.round(cursorHeight/2)
+ height: parent.height+cursorHeight
+ anchors.left: parent.left
+ anchors.right: parent.right
+ function handleMouse(mouse) {
+ if (mouse.buttons & Qt.LeftButton) {
+ pickerCursor.y = Math.max(0, Math.min(height, mouse.y)-cursorHeight)
+ }
+ }
+ onPositionChanged: {
+ handleMouse(mouse)
+ }
+ onPressed: handleMouse(mouse)
+ }
+
+ function setValue(val) {
+ pickerCursor.y = height * (1 - val)
+ }
+}
+
diff --git a/src/colorpicker/content/NumberBox.qml b/src/colorpicker/content/NumberBox.qml
new file mode 100644
index 00000000..fc2205bd
--- /dev/null
+++ b/src/colorpicker/content/NumberBox.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.15
+
+Row {
+ property alias caption: captionBox.text
+ property alias value: inputBox.text
+ property alias min: numValidator.bottom
+ property alias max: numValidator.top
+ property alias decimals: numValidator.decimals
+
+ width: 80;
+ height: 15
+ spacing: 4
+ //anchors.margins: 2
+ Text {
+ id: captionBox
+ width: 18; height: parent.height
+ color: "#AAAAAA"
+ font.pixelSize: 11; font.bold: true
+ }
+ PanelBorder {
+ height: parent.height
+ TextInput {
+ id: inputBox
+ color: "#AAAAAA"; selectionColor: "#FF7777AA"
+ font.pixelSize: 11
+ maximumLength: 10
+ focus: false
+ readOnly: true
+ selectByMouse: true
+ validator: DoubleValidator {
+ id: numValidator
+ bottom: 0; top: 1; decimals: 2
+ notation: DoubleValidator.StandardNotation
+ }
+ }
+ }
+}
+
+
diff --git a/src/colorpicker/content/PanelBorder.qml b/src/colorpicker/content/PanelBorder.qml
new file mode 100644
index 00000000..69dc4c53
--- /dev/null
+++ b/src/colorpicker/content/PanelBorder.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.15
+
+Rectangle {
+ width : 40; height : 15; radius: 2
+ border.width: 1; border.color: "#FF101010"
+ color: "transparent"
+ anchors.leftMargin: 1; anchors.topMargin: 3
+ clip: true
+ Rectangle {
+ anchors.fill: parent; radius: 2
+ anchors.leftMargin: -1; anchors.topMargin: -1
+ anchors.rightMargin: 0; anchors.bottomMargin: 0
+ border.width: 1; border.color: "#FF525255"
+ color: "transparent"
+ }
+}
+
+
diff --git a/src/colorpicker/content/SBPicker.qml b/src/colorpicker/content/SBPicker.qml
new file mode 100644
index 00000000..ab1b4c5a
--- /dev/null
+++ b/src/colorpicker/content/SBPicker.qml
@@ -0,0 +1,69 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+ property color hueColor : "blue"
+ property real saturation : pickerCursor.x/(width-2*r)
+ property real brightness : 1 - pickerCursor.y/(height-2*r)
+ property int r : colorHandleRadius
+
+ Rectangle {
+ x : r
+ y : r + parent.height - 2 * r
+ rotation: -90
+ transformOrigin: Item.TopLeft
+ width: parent.height - 2 * r
+ height: parent.width - 2 * r
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#FFFFFF" }
+ GradientStop { position: 1.0; color: root.hueColor }
+ }
+ }
+ Rectangle {
+ x: r
+ y: r
+ width: parent.width - 2 * r
+ height: parent.height - 2 * r
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "#FF000000" }
+ GradientStop { position: 0.0; color: "#00000000" }
+ }
+ }
+ Item {
+ id: pickerCursor
+ Rectangle {
+ width: r*2; height: r*2
+ radius: r
+ border.color: "black"; border.width: 2
+ color: "transparent"
+ Rectangle {
+ anchors.fill: parent; anchors.margins: 2;
+ border.color: "white"; border.width: 2
+ radius: width/2
+ color: "transparent"
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ x: r
+ y: r
+ function handleMouse(mouse) {
+ if (mouse.buttons & Qt.LeftButton) {
+
+ pickerCursor.x = Math.max(0,Math.min(mouse.x - r,width-2*r));
+ pickerCursor.y = Math.max(0,Math.min(mouse.y - r,height-2*r));
+
+
+// pickerCursor.x = Math.max(-r,Math.min(mouse.x - r,width+r));
+// pickerCursor.y = Math.max(-r,Math.min(mouse.y - r,height+r));
+
+// pickerCursor.x = Math.max(0, Math.min(width, mouse.x) - 2 * r);
+// pickerCursor.y = Math.max(0, Math.min(height, mouse.y) - 2 * r);
+ }
+ }
+ onPositionChanged: handleMouse(mouse)
+ onPressed: handleMouse(mouse)
+ }
+}
+
diff --git a/src/controls/FluCalendarView.qml b/src/controls/FluCalendarView.qml
index cb7fc325..d7b5129d 100644
--- a/src/controls/FluCalendarView.qml
+++ b/src/controls/FluCalendarView.qml
@@ -44,7 +44,6 @@ Item {
return {type:3,date:date,name:"",isDecade:isDecade}
}
-
function updateDecade(date){
list_model.clear()
var year = date.getFullYear()
diff --git a/src/controls/FluColorPicker.qml b/src/controls/FluColorPicker.qml
new file mode 100644
index 00000000..2cb25070
--- /dev/null
+++ b/src/controls/FluColorPicker.qml
@@ -0,0 +1,52 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Window 2.15
+import FluentUI 1.0
+
+
+Button{
+ id:control
+ width: 36
+ height: 36
+ implicitWidth: width
+ implicitHeight: height
+ background:
+ Rectangle{
+ id:layout_color
+ radius: 5
+ color: container.colorValue
+ border.color: {
+ if(hovered)
+ return FluTheme.primaryColor.light
+ return FluTheme.isDark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
+ }
+ border.width: 1
+ }
+ contentItem: Item{}
+ onClicked: {
+ popup.showPopup()
+ }
+ Popup{
+ id:popup
+ height: container.height
+ width: container.width
+ background: FluColorView{
+ id:container
+ }
+ contentItem: Item{}
+ function showPopup() {
+ var pos = control.mapToItem(null, 0, 0)
+ if(window.height>pos.y+control.height+popup.height){
+ popup.y = control.height
+ } else if(pos.y>popup.height){
+ popup.y = -popup.height
+ } else {
+ popup.y = window.height-(pos.y+popup.height)
+ }
+ popup.x = -(popup.width-control.width)/2
+ popup.open()
+ }
+ }
+
+}
diff --git a/src/controls/FluColorView.qml b/src/controls/FluColorView.qml
new file mode 100644
index 00000000..d74059c5
--- /dev/null
+++ b/src/controls/FluColorView.qml
@@ -0,0 +1,29 @@
+import QtQuick 2.15
+import "../colorpicker"
+
+Item {
+
+ width: color_picker.width+10
+ height: color_picker.height
+
+ property alias colorValue: color_picker.colorValue
+
+ FluArea{
+ anchors.fill: parent
+ radius: 5
+
+ FluShadow{
+ radius: 5
+ }
+
+ ColorPicker{
+ id:color_picker
+ }
+ }
+
+ function setColor(color) {
+ color_picker.setColor(color)
+ }
+
+}
+
diff --git a/src/res.qrc b/src/res.qrc
index 27570524..17ceafb7 100644
--- a/src/res.qrc
+++ b/src/res.qrc
@@ -49,5 +49,13 @@
controls/FluFocusRectangle.qml
controls/FluCarousel.qml
controls/FluBadge.qml
+ controls/FluColorView.qml
+ controls/FluColorPicker.qml
+ colorpicker/ColorPicker.qml
+ colorpicker/content/Checkerboard.qml
+ colorpicker/content/ColorSlider.qml
+ colorpicker/content/NumberBox.qml
+ colorpicker/content/PanelBorder.qml
+ colorpicker/content/SBPicker.qml