《QT实用小工具·三十九》仿 Windows10 画图3D 的颜色选择器, 但更加强大

news2024/12/28 17:59:59

1、概述
源码放在文章末尾

该项目实现了仿 Windows10 画图3D 的颜色选择器,功能更加丰富更加强大。
在这里插入图片描述

项目部分代码如下所示:

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtGraphicalEffects 1.15

Item {
    id: root
    width: 460
    height: 500
    scale: 0
    opacity: 0
    enabled: false

    property bool movable: true
    property alias title: contentText.text
    property color initColor: "white"
    readonly property color currentColor: pickerRect.currentColor

    onInitColorChanged: pickerRect.setColor(initColor);

    signal accepted();
    signal rejected();

    function open() {
        focus = true;
        enabled = true;
    }

    function hide() {
        focus = false;
        enabled = false;
    }

    Keys.onEscapePressed: cancelButton.clicked();

    NumberAnimation on scale {
        running: root.enabled
        duration: 350
        easing.type: Easing.OutBack
        easing.overshoot: 1.0
        to: 1.0
    }

    NumberAnimation on opacity {
        running: root.enabled
        duration: 300
        easing.type: Easing.OutQuad
        to: 1.0
    }

    NumberAnimation on scale {
        running: !root.enabled
        duration: 300
        easing.type: Easing.InBack
        easing.overshoot: 1.0
        to: 0.0
    }

    NumberAnimation on opacity {
        running: !root.enabled
        duration: 250
        easing.type: Easing.OutQuad
        to: 0.0
    }

    RectangularGlow {
        width: parent.width + 4
        height: parent.height + 4
        anchors.centerIn: parent
        glowRadius: 4
        spread: 0.2
        color: "#206856E6"
        cornerRadius: 4
    }

    Rectangle {
        anchors.fill: parent
        color: "#f6f6f6"
        border.color: "#aea4ee"
    }

    MouseArea {
        anchors.fill: parent
        enabled: root.movable

        property point startPos: Qt.point(0, 0)
        property point offsetPos: Qt.point(0, 0)

        onClicked: (mouse) => mouse.accepted = false;
        onPressed: (mouse) => {
            startPos = Qt.point(mouse.x, mouse.y);
            cursorShape = Qt.SizeAllCursor;
        }
        onReleased: (mouse) => {
            startPos = Qt.point(mouse.x, mouse.y);
            cursorShape = Qt.ArrowCursor;
        }
        onPositionChanged: (mouse) => {
            if (pressed) {
                offsetPos = Qt.point(mouse.x - startPos.x, mouse.y - startPos.y);
                root.x = root.x + offsetPos.x;
                root.y = root.y + offsetPos.y;
            }
        }

        Text {
            id: contentText
            height: 20
            anchors.top: parent.top
            anchors.topMargin: 15
            anchors.left: parent.left
            anchors.leftMargin: 25
            anchors.right: parent.right
            font.family: "微软雅黑"
            color: "#222255"
            text: qsTr("选择新颜色")
            antialiasing: true
            verticalAlignment: Text.AlignVCenter
        }

        Item {
            id: pickerRect
            width: 330
            height: 290
            anchors.top: contentText.bottom
            anchors.left: contentText.left
            anchors.leftMargin: -cursorWidth * 0.5

            property real cursorWidth: 30
            property color hueColor: {
                let 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";
                }
            }
            property real saturation: colorPickerCursor.x / (width - cursorWidth)
            property real brightness: 1 - colorPickerCursor.y / (height - cursorWidth)
            property color currentColor: Qt.hsva(hueSlider.value, saturation, brightness, alphaSlider.value)
            property color __color: Qt.rgba(0, 0, 0, 0)

            function setColor(color) {
                alphaSlider.x = alphaPicker.width == 0 ? 0 : (alphaPicker.width - alphaSlider.width) * color.a;
                hueSlider.x = (huePicker.width - hueSlider.width) * (Math.max(color.hsvHue, 0));
                colorPickerCursor.x = color.hsvSaturation * (width - cursorWidth);
                colorPickerCursor.y = (1.0 - color.hsvValue) * (height - cursorWidth);
            }

            function fromColor() {
                pickerRect.setColor(Qt.rgba(parseInt(redEditor.text) / 255.
                                            , parseInt(greenEditor.text) / 255.
                                            , parseInt(blueEditor.text) / 255.
                                            , parseInt(alphaEditor.text) / 255.));
            }

            function fromArgbColor() {
                __color = '#' + argbEditor.text;
                pickerRect.setColor(__color);
            }

            onCurrentColorChanged: {
                redEditor.text = (currentColor.r * 255).toFixed(0);
                greenEditor.text = (currentColor.g * 255).toFixed(0);
                blueEditor.text = (currentColor.b * 255).toFixed(0);
                alphaEditor.text = (currentColor.a * 255).toFixed(0);
                argbEditor.text = currentColor.toString().replace("#", "");
            }

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

            Rectangle {
                id: colorPickerCursor
                width: pickerRect.cursorWidth
                height: pickerRect.cursorWidth
                border.color: "#e6e6e6"
                border.width: 1
                color: pickerRect.currentColor

                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 {
                x: pickerRect.cursorWidth
                y: pickerRect.cursorWidth
                anchors.fill: parent

                function handleCursorPos(x, y) {
                    let halfWidth = pickerRect.cursorWidth * 0.5;
                    colorPickerCursor.x = Math.max(0, Math.min(width , x + halfWidth) - pickerRect.cursorWidth);
                    colorPickerCursor.y = Math.max(0, Math.min(height, y + halfWidth) - pickerRect.cursorWidth);
                }

                onPositionChanged: (mouse) => handleCursorPos(mouse.x, mouse.y);
                onPressed: (mouse) => {
                    colorPickerCursor.scale = 0.7;
                    handleCursorPos(mouse.x, mouse.y);
                }
                onReleased: colorPickerCursor.scale = 1.0;
            }
        }

        Item {
            id: previewItem
            width: 90
            height: 90
            anchors.left: pickerRect.right
            anchors.leftMargin: 10
            anchors.top: contentText.bottom
            anchors.topMargin: 15

            Grid {
                id: previwBackground
                anchors.fill: parent
                rows: 11
                columns: 11
                clip: true

                property real cellWidth: width / columns
                property real cellHeight: height / rows

                Repeater {
                    model: parent.columns * parent.rows

                    Rectangle {
                        width: previwBackground.cellWidth
                        height: width
                        color: (index % 2 == 0) ? "gray" : "transparent"
                    }
                }
            }

            Rectangle {
                anchors.fill: parent
                anchors.margins: -2
                color: pickerRect.currentColor
                border.color: "#e6e6e6"
                border.width: 2
            }
        }

        component ColorEditor: ColumnLayout {
            id: __layout
            width: previewItem.width
            height: 50

            property alias label: label.text
            property alias text: input.text
            property alias validator: input.validator

            signal textEdited();
            signal accepted();

            Text {
                id: label
                font.family: "微软雅黑"
                color: "#222255"
                verticalAlignment: Text.AlignVCenter
                Layout.fillWidth: true
            }

            Rectangle {
                clip: true
                color: "transparent"
                border.color: "#e6e6e6"
                border.width: 2
                Layout.fillHeight: true
                Layout.fillWidth: true

                TextInput {
                    id: input
                    leftPadding: 10
                    rightPadding: 10
                    selectionColor: "#398ed4"
                    selectByMouse: true
                    anchors.fill: parent
                    horizontalAlignment: TextInput.AlignRight
                    verticalAlignment: TextInput.AlignVCenter
                    onTextEdited: __layout.textEdited();
                    onAccepted: __layout.accepted();
                }
            }
        }

        Column {
            anchors.top: previewItem.bottom
            anchors.topMargin: 10
            anchors.left: previewItem.left
            spacing: 6

            ColorEditor {
                id: redEditor
                label: "红色"
                validator: IntValidator { top: 255; bottom: 0 }
                onAccepted: pickerRect.fromColor();
            }

            ColorEditor {
                id: greenEditor
                label: "绿色"
                validator: IntValidator { top: 255; bottom: 0 }
                onAccepted: pickerRect.fromColor();
            }

            ColorEditor {
                id: blueEditor
                label: "蓝色"
                validator: IntValidator { top: 255; bottom: 0 }
                onAccepted: pickerRect.fromColor();
            }

            ColorEditor {
                id: alphaEditor
                label: "透明度"
                validator: IntValidator { top: 255; bottom: 0 }
                onAccepted: pickerRect.fromColor();
            }

            ColorEditor {
                id: argbEditor
                label: "十六进制 (ARGB)"
                validator: RegularExpressionValidator { regularExpression: /[0-9a-fA-F]{0,8}/ }
                onAccepted: pickerRect.fromArgbColor();
            }
        }

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

        Button {
            id: confirmButton
            width: 200
            height: alphaPickerItem.height
            anchors.top: alphaPickerItem.bottom
            anchors.topMargin: 25
            anchors.left: alphaPickerItem.left
            text: qsTr("确定")
            hoverEnabled: true
            topInset: down ? 1 : 0
            bottomInset: topInset
            leftInset: topInset
            rightInset: topInset
            font.family: "微软雅黑"
            onClicked: {
                root.initColor = root.currentColor;
                root.hide();
                root.accepted();
            }
        }

        Button {
            id: cancelButton
            width: 200
            height: alphaPickerItem.height
            anchors.top: alphaPickerItem.bottom
            anchors.topMargin: 25
            anchors.right: parent.right
            anchors.rightMargin: 25
            text: qsTr("取消")
            hoverEnabled: true
            topInset: down ? 1 : 0
            bottomInset: topInset
            leftInset: topInset
            rightInset: topInset
            font.family: "微软雅黑"
            onClicked: {
                pickerRect.setColor(root.initColor);
                root.hide();
                root.rejected();
            }
        }
    }
}

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1621999.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【踩坑】libtorch load 报错 No such file or directory

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;请不吝给个[点赞、收藏、关注]哦~ 目录 报错背景 报错原因 解决方法 方法一&#xff1a;把你的编译配置转为release版本 方法二&#xff1a;安装debug版本的libtorch 报错背景…

算法学习001-圆桌问题 中小学算法思维学习 信奥算法解析 c++实现

目录 算法学习001-圆桌问题 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 算法学习001-圆桌问题 一、题目要求 1、编程实现 圆桌边围坐着2n个人&#xff0c;其中n个人是好人&#xff0c…

Redis 安装及配置教程(Windows)【安装】

文章目录 一、简介一、 下载1. GitHub 下载2. 其它渠道 二、 安装1. ZIP2. MSI 软件 / 环境安装及配置目录 一、简介 Redis 官网地址&#xff1a;https://redis.io/   Redis 源码地址&#xff1a;https://github.com/redis/redis   Redis 官网安装地址&#xff08;无Windo…

基于SSM的物业管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的物业管理系统2拥有三种角色 管理员&#xff1a;用户管理、物业管理、房产信息管理、小区概况管理、开发商管理、收费标准管理、物业公司管理等 物业&#xff1a;住户管理、收费…

vector的使用(部分接口)

1.vector的使用 1.1vector的定义 (constructor)构造函数声明接口说明vector()无参构造vector (const vector& x)拷贝构造 1.2vector iterator 的使用 iterator的使用接口说明begin end获取第一个数据位置的iterator/const_iterator&#xff0c; 获取最后一个数据的下一个位…

【数据结构】单链表的特点

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;数据结构 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

UML——类图详解

目录 1. 前言 2. 类图概述 3. 类图表示法 3.1 类的表示方式 3.2 类与类之间关系的表示方式 (1)继承(泛化)关系 (2)实现关系 (3)依赖关系 (4)一般关联关系 (5)聚合关系 (6)组合关系 1. 前言 UML全称(Unified Modeling Language)&#xff0c;译为统一建模语言&#x…

Android自定义ListView单击事件失效的解决方法

因为自带的listView不能满足项目需求&#xff0c;通过实现自己的Adapter去继承ArrayAdapter 来实现自定义ListView的Item项目。 出现点击ListView的每一项都不会执行setOnItemClickListener 里面的onItemClick 方法。 原因是item里面存在一些子控件&#xff0c;默认点击获取的…

使用 PhpMyAdmin 安装 LAMP 服务器

使用 PhpMyAdmin 安装 LAMP 服务器非常简单。按照下面所示的步骤&#xff0c;我们将拥有一个完全可运行的 LAMP 服务器&#xff08;Linux、Apache、MySQL/MariaDB 和 PHP&#xff09;。 什么是 LAMP 服务器&#xff1f; LAMP 代表 Linux、Apache、MySQL 和 PHP。它们共同提供…

如何在PostgreSQL中实现分布式事务,特别是在多节点集群环境中?

文章目录 解决方案&#xff1a;使用Citus实现分布式事务步骤一&#xff1a;安装和配置Citus步骤二&#xff1a;定义分布式表和分布键步骤三&#xff1a;执行分布式事务示例代码 总结 在PostgreSQL中实现分布式事务&#xff0c;特别是在多节点集群环境中&#xff0c;是一个复杂但…

c++ - 模板(一)

文章目录 一、函数模板 一、函数模板 1、概念 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定 类型版本。 2、原理 函数模板是一个蓝图&#xff0c;它本身并不是函数&#xff0c;是编译器用…

【学习】如何高效地进行集成测试

在软件开发的过程中&#xff0c;测试环节至关重要。而在这其中&#xff0c;集成测试更是保证软件质量的关键步骤之一。本文将探讨如何高效地进行集成测试&#xff0c;以确保软件的稳定性和可靠性。 一、什么是集成测试 集成测试是指在单元测试的基础上&#xff0c;将模块按照设…

opencv可视化图片-----c++

可视化图片 #include <opencv2/opencv.hpp> #include <opencv2/core.hpp> #include <filesystem>// 将数据类型转换为字符串 std::string opencvTool::type2str(int type) {std::string r;uchar depth type & CV_MAT_DEPTH_MASK;uchar chans 1 (typ…

Redis入门到通关之Redis网络模型-用户空间和内核态空间

文章目录 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后端开发者。 博客特色&#xff1a; 在我的…

【行为型模式】解释器模式

一、解释器模式概述 解释器模式定义&#xff1a;给分析对象定义一个语言&#xff0c;并定义该语言的文法表示&#xff0c;再设计一个解析器来解释语言中的句子。也就是说&#xff0c;用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口&#xff0c;该接口…

STM32中的PWM

一、介绍 二、制作一个呼吸灯的效果&#xff08;使用PWM&#xff09; 原理是中心对齐的方式 学会分析复用管脚&#xff08;根据手册&#xff09; 配置 更正:是 最后一个输出的模式 最后生成代码 三、代码 要修改的业务代码 改代码&#xff0c;实现呼吸灯

科技赋能无人零售

科技赋能无人零售&#xff0c;使其具备以下独特优势&#xff1a; 1. 全天候无缝服务 &#xff1a;无人零售店依托科技&#xff0c;实现24小时不间断运营&#xff0c;不受人力限制&#xff0c;满足消费者随时购物需求&#xff0c;尤其惠及夜间工作者、夜猫子及急需购物者&…

聊聊.NET Core处理全局异常有那些方法

简述 处理全局异常的方法有IExceptionFilter&#xff08;异常处理&#xff09;&#xff0c;使用中间件异常处理&#xff0c;使用框架自带异常中间件等。考点 考察对异常处理方式的熟悉程度和广度&#xff0c;以及对中间件、过滤器熟练程度。 下面分别具体介绍三种处理异常的…

k-均值聚类

K均值聚类&#xff08;K-means clustering&#xff09;是一种常用的无监督学习方法&#xff0c;用于将一组数据点划分为K个簇&#xff08;cluster&#xff09;。 它的目标是将相似的数据点归到同一个簇中&#xff0c;同时使得不同簇之间的数据点尽可能不相似。K均值聚类算法的…

Golang | Leetcode Golang题解之第47题全排列II

题目&#xff1a; 题解&#xff1a; func permuteUnique(nums []int) (ans [][]int) {sort.Ints(nums)n : len(nums)perm : []int{}vis : make([]bool, n)var backtrack func(int)backtrack func(idx int) {if idx n {ans append(ans, append([]int(nil), perm...))return}…