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

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.mfbz.cn/a/571250.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于OSAL 实现UART、LED、ADC等基础示例 4

1 UART 实验目的 串口在我们开发单片机项目是很重要的&#xff0c;可以观察我们的代码运行情况&#xff0c;本节的目的就 是实现串口双工收发。 虽然说 osal 相关的代码已经跟硬件关系不大了&#xff0c;但是我们还是来贴出相关的硬件原理图贴出来。 1.1 初始化 osal_init_s…

Leetcode743. 网络延迟时间

Every day a Leetcode 题目来源&#xff1a;743. 网络延迟时间 本题需要用到单源最短路径算法 Dijkstra&#xff0c;现在让我们回顾该算法&#xff0c;其主要思想是贪心。 将所有节点分成两类&#xff1a;已确定从起点到当前点的最短路长度的节点&#xff0c;以及未确定从起…

分类分析|KNN分类模型及其Python实现

KNN分类模型及其Python实现 1. KNN算法思想2. KNN算法步骤2.1 KNN主要优点2.2 KNN主要缺点 3. Python实现KNN分类算法3.1 自定义方法实现KNN分类3.2 调用scikit-learn模块实现KNN分类 4. K值的确定 在之前文章 分类分析|贝叶斯分类器及其Python实现中&#xff0c;我们对分类分…

DHCP的原理与配置

一.了解DHCP服务 1. DHCP (Dynamic Host Configuration Protocol)动态主机配置协议 是由Internet工作小组设计开发的&#xff0c;专门用于为TCP/IP网络中的计算机自动分配TCP/IP参数的协议 DHCP协议采用的是UDP作为传输协议&#xff0c;是给网络内的客户机自动分配IP地址&…

Redis入门到通关之Redis实现Session共享

文章目录 ☃️前期概要☃️基于Session实现登录方案☃️现有方案存在的问题☃️Redis代替Session的业务流程❄️❄️设计key的结构❄️❄️设计key的具体细节❄️❄️整体访问流程 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博…

羊大师分析,羊奶和牛奶哪个更适合夏天喝?

羊大师分析&#xff0c;羊奶和牛奶哪个更适合夏天喝&#xff1f; 羊奶和牛奶都是营养丰富的饮品&#xff0c;适合不同人群在不同季节饮用。在夏天&#xff0c;选择羊奶还是牛奶主要取决于个人的体质、口味偏好以及需求。 羊奶的营养价值较高&#xff0c;含有丰富的蛋白质、矿物…

ESP8266+STM32+阿里云保姆级教程(AT指令+MQTT)

前言&#xff1a;在开发过程中&#xff0c;几乎踩便了所有大坑小坑总结出的文章&#xff0c;我是把坑踩满了&#xff0c;帮助更过小白快速上手&#xff0c;如有错误之处&#xff0c;还麻烦各位大佬帮忙指正、 目录 一、ESP-01s介绍 1、ESP-01s管脚功能&#xff1a; 模组启动模…

元数据管理和数据目录对于现代数据平台的重要性——Lakehouse架构(四)

文章目录 前言解读元数据技术元数据业务元数据 元存储和数据目录如何协同工作&#xff1f;数据目录的特点查询、检索和发现数据数据分类数据治理数据血缘 前言 Lakehouse 架构中的存储层负责存储整个平台的数据&#xff0c;要查询存储的这些数据&#xff0c;我们需要一个数据目…

xgp怎么取消续费 微软商店xgp会员取消自动续费详细教程

xgp怎么取消续费 微软商店xgp会员取消自动续费详细教程 XGP这个游戏平台小伙伴们并不陌生吧&#xff0c;它是微软Xbox游戏部门推出的游戏租赁制会员服务&#xff0c;主要用于主机和PC两个平台。这个平台的会员就可以免费享受多款大制作游戏&#xff0c;而且每个月还会自动更新…

ruoyi-nbcio-plus基于vue3的flowable收回任务后重新进行提交表单的处理

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

JAVA毕业设计137—基于Java+Springboot+Vue的物流快递仓库管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的物流快递仓库管理系统(源代码数据库)137 一、系统介绍 本项目前后端分离&#xff0c;分为员工、销售员、仓库员、商品管理员、超级管理员五种角色 1、员工…

Linux 的情况下实现贪吃蛇 -- 第二十八天

1. 打印地图 keypad(stdsrc,1) 参数表示是否接收&#xff0c;1表示接收指令 2.思路&#xff1a;初始化initNcurses()&#xff0c; 封装地图函数实现地图gamePic&#xff08;&#xff09; 分三部分实现&#xff1a;2.1: 在第0行&#xff1a;打印 "--",&quo…

矩阵连乘算法

矩阵连乘&#xff1a; #include<iostream> #define inf 0x7fffffff using namespace std; int a[256] { 0 };//存储矩阵的行和列 int m[256][256] { 0 };//存储i到j的最少计算次数 int s[256][256] { 0 };//存储i到j的中转站k void m_print(int i, int j) {if (i …

javaWeb项目-房屋房租租赁系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JSP技术 JSP(Jav…

数据结构-二叉树-链式

一、链式二叉树的结构 typedef int BTNodeDataType; typedef struct BTNode {BTNodeDataType data;struct BTNode* left;struct BTNode* right; }BTNode; 二叉树的前中后序遍历 前序&#xff1a;根左右 中序&#xff1a;左根右 后序&#xff1a;左右根 void PreOrder(BTNo…

栈 、队列

1.stack的介绍和使用 1.1stack的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 1.2 stack的使用 函数说明 接口说明 stack() 构造空的栈 empty() 检测stack是否为空 size…

Opencv | 边缘检测 轮廓信息

目录 一. 边缘检测1. 边缘的定义2. Sobel算子 边缘提取3. Scharr算子 边缘提取4. Laplacian算子 边缘提取5. Canny 边缘检测算法5.1 计算梯度的强度及方向5.2 非极大值抑制5.3 双阈值检测5.4 抑制孤立弱边缘 二. 轮廓信息1. 获取轮廓信息2. 画轮廓 一. 边缘检测 1. 边缘的定义…

【QT】Ubuntu22.04 配置 QT6.5 LTS

【QT】Ubuntu22.04 配置 QT6.5 LTS 文章目录 【QT】Ubuntu22.04 配置 QT6.5 LTS1.注册QT Group的账号2.安装QT Creator3.启动QT Creator报错from 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.4.运行QT的demoReference 1.注册QT Group的…

mysql buffer pool详解

介绍 缓冲池是InnoDB在访问表和索引数据时缓存的主内存区域。缓冲池允许直接从内存访问频繁使用的数据&#xff0c;这加快了处理速度。在专用服务器上&#xff0c;通常会将多达80%的物理内存分配给缓冲池。 为了提高大容量读操作的效率&#xff0c;缓冲池被划分为可能包含多行…

类与对象(三) 拷贝构造与赋值运算符重载

目录 1.拷贝构造 2.运算符重载&#xff08;日期类举例&#xff09; 1. 2.和 3. > > < < 4.赋值运算符重载 5.- 与- 6. -- 7.日期 - 日期 3.const成员函数 4.<<和>>重载 5.取地址重载 1.拷贝构造 拷贝构造也是一个构造函数。我们前…
最新文章