使用 Qt QGraphicsView/QGraphicsScene 绘制色轮

使用 Qt QGraphicsView/QGraphicsScene 绘制色轮

本文介绍如何在 Qt 中利用 QGraphicsViewQGraphicsScene 实现基础圆形绘制,以及进阶的色轮(Color Wheel)效果。
色轮是色彩选择器的常见控件,广泛应用于图形设计、绘画和 UI 取色等场景。本文将详细讲解两种常见的色轮实现方式,并配以完整代码和效果图。


一、QGraphicsView/QGraphicsScene 绘制圆形

1. 原理说明

Qt 的 QGraphicsView/QGraphicsScene 提供了强大的 2D 图形视图框架。QGraphicsScene 负责管理所有图形项,QGraphicsView 负责显示场景内容。
绘制圆形时,常用 QGraphicsEllipseItem,通过设置其矩形区域和填充颜色即可实现。

2. 代码实现

假设我们已经创建了一个 Qt Widgets Application 项目 Scence1。在类的构造函数中创建 QGraphicsSceneQGraphicsView,并添加到 QVBoxLayout 布局中:

Scence1::Scence1(QWidget *parent): QWidget(parent)
{// 创建场景QGraphicsScene* scene = new QGraphicsScene(this);// 创建视图并设置场景QGraphicsView* view = new QGraphicsView(scene, this);paintEllipse(view, scene); // 绘制椭圆//paintColorWheel(view, scene); // 绘制色轮// 使用布局管理器添加视图到窗口QVBoxLayout* layout = new QVBoxLayout(this);layout->addWidget(view);setLayout(layout);ui.setupUi(this);
}void Scence1::paintEllipse(QGraphicsView* view, QGraphicsScene* scene)
{// 设置画笔为蓝色,宽度为1QPen pen;pen.setColor(QColor(0, 0, 255));pen.setWidth(1);// 圆的半径int circleR = 160;// 创建一个椭圆QGraphicsEllipseItem* myEllipseItem = new QGraphicsEllipseItem();myEllipseItem->setRect(0, 0, 2 * circleR, 2 * circleR);myEllipseItem->setPen(pen);myEllipseItem->setBrush(QColor(0, 0, 255));// 添加到场景scene->addItem(myEllipseItem);// 设置视图的场景view->setScene(scene);
}

这样我们可以得到一个蓝色的圆形,完成了第一步:

二、QGraphicsView/QGraphicsScene 实现色轮

色轮是色彩学中常用的工具,通常以 HSV 色彩空间为基础。HSV 色彩空间将颜色分为色相(Hue)、饱和度(Saturation)、明度(Value),非常适合用于色轮的实现。

原理说明

色轮的本质是将色相(Hue)映射到圆周上,不同的实现方式可以带来不同的视觉效果和性能表现。
常见的两种实现方式如下:

方式一:多个扇形拼接色轮

实现思路
将圆分成若干个扇形,每个扇形代表一种色相(Hue)。
通过 HSV 颜色模型,改变色相值,生成不同颜色。
使用 QPainterPath 绘制扇形,并填充对应颜色。
每个扇形作为一个 QGraphicsPathItem 添加到 scene,便于后续交互。
代码实现

void Scence1::paintColorWheel(QGraphicsView* view, QGraphicsScene* scene)
{// 设置圆的半径int radius = 150;// 设置扇形数量int numSegments = 360;// 遍历每个扇形for (int i = 0; i < numSegments; ++i) {// 计算当前扇形的起始角度和结束角度qreal startAngle = i * 16;qreal endAngle = (i + 1) * 16;// 创建一个 QPainterPath 对象QPainterPath path;// 移动到圆心path.moveTo(0, 0);// 绘制扇形路径path.arcTo(-radius, -radius, 2 * radius, 2 * radius, startAngle, 16);// 填充颜色QColor color = QColor::fromHsv(i, 255, 255);QBrush brush(color);// 创建一个 QGraphicsPathItem 对象QGraphicsPathItem* item = new QGraphicsPathItem(path);item->setBrush(brush);// 添加到场景scene->addItem(item);}// 设置视图的场景view->setScene(scene);
}

这样我们就实现了一个简单的色轮效果:

方式二:使用渐变色填充色轮

实现思路
通过 QConicalGradient 创建圆锥形渐变,渐变的颜色从中心向外辐射。
使用 QGraphicsEllipseItem 绘制一个完整的圆形作为色轮的底图。
代码实现

void Scence1::paintColorWheel(QGraphicsView* view, QGraphicsScene* scene)
{// 设置圆的半径int radius = 150;// 创建一个 QConicalGradient 渐变对象QConicalGradient gradient(0, 0, 0);// 添加颜色停靠点for (int i = 0; i < 360; i += 10) {gradient.setColorAt(i / 360.0, QColor::fromHsv(i, 255, 255));}// 创建一个 QGraphicsEllipseItem 对象QGraphicsEllipseItem* item = new QGraphicsEllipseItem();item->setRect(-radius, -radius, 2 * radius, 2 * radius);// 设置渐变填充item->setBrush(gradient);// 添加到场景scene->addItem(item);// 设置视图的场景view->setScene(scene);
}

这种方式实现的色轮更加平滑,过渡自然:

三、总结

本文介绍了如何使用 Qt 的 QGraphicsViewQGraphicsScene 实现圆形及色轮的绘制。
通过两种方式实现色轮:一种是通过多个扇形拼接而成,另一种是使用渐变色填充。读者可以根据需求选择合适的实现方式。


附录:完整代码

#include "scence1.h"
#include "ui_scence1.h"Scence1::Scence1(QWidget *parent): QWidget(parent)
{// 创建场景QGraphicsScene* scene = new QGraphicsScene(this);// 创建视图并设置场景QGraphicsView* view = new QGraphicsView(scene, this);paintEllipse(view, scene); // 绘制椭圆//paintColorWheel(view, scene); // 绘制色轮// 使用布局管理器添加视图到窗口QVBoxLayout* layout = new QVBoxLayout(this);layout->addWidget(view);setLayout(layout);ui.setupUi(this);
}void Scence1::paintEllipse(QGraphicsView* view, QGraphicsScene* scene)
{// 设置画笔为蓝色,宽度为1QPen pen;pen.setColor(QColor(0, 0, 255));pen.setWidth(1);// 圆的半径int circleR = 160;// 创建一个椭圆QGraphicsEllipseItem* myEllipseItem = new QGraphicsEllipseItem();myEllipseItem->setRect(0, 0, 2 * circleR, 2 * circleR);myEllipseItem->setPen(pen);myEllipseItem->setBrush(QColor(0, 0, 255));// 添加到场景scene->addItem(myEllipseItem);// 设置视图的场景view->setScene(scene);
}void Scence1::paintColorWheel(QGraphicsView* view, QGraphicsScene* scene)
{// 设置圆的半径int radius = 150;// 设置扇形数量int numSegments = 360;// 遍历每个扇形for (int i = 0; i < numSegments; ++i) {// 计算当前扇形的起始角度和结束角度qreal startAngle = i * 16;qreal endAngle = (i + 1) * 16;// 创建一个 QPainterPath 对象QPainterPath path;// 移动到圆心path.moveTo(0, 0);// 绘制扇形路径path.arcTo(-radius, -radius, 2 * radius, 2 * radius, startAngle, 16);// 填充颜色QColor color = QColor::fromHsv(i, 255, 255);QBrush brush(color);// 创建一个 QGraphicsPathItem 对象QGraphicsPathItem* item = new QGraphicsPathItem(path);item->setBrush(brush);// 添加到场景scene->addItem(item);}// 设置视图的场景view->setScene(scene);
}void Scence1::paintColorWheel(QGraphicsView* view, QGraphicsScene* scene)
{// 设置圆的半径int radius = 150;// 创建一个 QConicalGradient 渐变对象QConicalGradient gradient(0, 0, 0);// 添加颜色停靠点for (int i = 0; i < 360; i += 10) {gradient.setColorAt(i / 360.0, QColor::fromHsv(i, 255, 255));}// 创建一个 QGraphicsEllipseItem 对象QGraphicsEllipseItem* item = new QGraphicsEllipseItem();item->setRect(-radius, -radius, 2 * radius, 2 * radius);// 设置渐变填充item->setBrush(gradient);// 添加到场景scene->addItem(item);// 设置视图的场景view->setScene(scene);
}void Scence1::paintAxis(QGraphicsScene* scene, int hueCircleR)
{// 画三条分割线QPen pen;pen.setWidth(1);pen.setColor(QColor(0, 0, 0));pen.setStyle(Qt::DashDotLine);pen.setWidth(1);// 分割线1:210度到30度QGraphicsLineItem* splitLine1 = new QGraphicsLineItem();splitLine1->setLine(QLineF(hueCircleR + hueCircleR * cos(210 * 3.14159 / 180), hueCircleR - hueCircleR * sin(210 * 3.14159 / 180),hueCircleR + hueCircleR * cos(30 * 3.14159 / 180), hueCircleR - hueCircleR * sin(30 * 3.14159 / 180)));splitLine1->setPen(pen);// 分割线2:270度到90度QGraphicsLineItem* splitLine2 = new QGraphicsLineItem();splitLine2->setLine(QLineF(hueCircleR + hueCircleR * cos(270 * 3.14159 / 180), hueCircleR - hueCircleR * sin(270 * 3.14159 / 180),hueCircleR + hueCircleR * cos(90 * 3.14159 / 180), hueCircleR - hueCircleR * sin(90 * 3.14159 / 180)));splitLine2->setPen(pen);// 分割线3:330度到150度QGraphicsLineItem* splitLine3 = new QGraphicsLineItem();splitLine3->setLine(QLineF(hueCircleR + hueCircleR * cos(330 * 3.14159 / 180), hueCircleR - hueCircleR * sin(330 * 3.14159 / 180),hueCircleR + hueCircleR * cos(150 * 3.14159 / 180), hueCircleR - hueCircleR * sin(150 * 3.14159 / 180)));splitLine3->setPen(pen);// 添加分割线到场景scene->addItem(splitLine1);scene->addItem(splitLine2);scene->addItem(splitLine3);// 设置字体QFont font("Arial", 8);font.setBold(true);// 添加文字标注QGraphicsTextItem* textItem1 = new QGraphicsTextItem();textItem1->setPlainText(QString("CB\n210"));textItem1->setFont(font);textItem1->setPos(hueCircleR + hueCircleR * cos(210 * 3.14159 / 180) - 30, hueCircleR - hueCircleR * sin(210 * 3.14159 / 180) - 20);QGraphicsTextItem* textItem2 = new QGraphicsTextItem();textItem2->setPlainText(QString("30\nRY"));textItem2->setFont(font);textItem2->setPos(hueCircleR + hueCircleR * cos(30 * 3.14159 / 180) + 5, hueCircleR - hueCircleR * sin(30 * 3.14159 / 180) - 20);QGraphicsTextItem* textItem3 = new QGraphicsTextItem();textItem3->setPlainText(QString("BM 270"));textItem3->setFont(font);textItem3->setPos(hueCircleR + hueCircleR * cos(270 * 3.14159 / 180) - 30, hueCircleR - hueCircleR * sin(270 * 3.14159 / 180) + 0);QGraphicsTextItem* textItem4 = new QGraphicsTextItem();textItem4->setPlainText(QString("90 YG"));textItem4->setFont(font);textItem4->setPos(hueCircleR + hueCircleR * cos(90 * 3.14159 / 180) - 20, hueCircleR - hueCircleR * sin(90 * 3.14159 / 180) - 20);QGraphicsTextItem* textItem5 = new QGraphicsTextItem();textItem5->setPlainText(QString("330\nMR"));textItem5->setFont(font);textItem5->setPos(hueCircleR + hueCircleR * cos(330 * 3.14159 / 180) + 5, hueCircleR - hueCircleR * sin(330 * 3.14159 / 180) - 20);QGraphicsTextItem* textItem6 = new QGraphicsTextItem();textItem6->setPlainText(QString("GC\n150"));textItem6->setFont(font);textItem6->setPos(hueCircleR + hueCircleR * cos(150 * 3.14159 / 180) - 30, hueCircleR - hueCircleR * sin(150 * 3.14159 / 180) - 20);// 添加文字到场景scene->addItem(textItem1);scene->addItem(textItem2);scene->addItem(textItem3);scene->addItem(textItem4);scene->addItem(textItem5);scene->addItem(textItem6);
}Pos(hueCircleR + hueCircleR * cos(150 * 3.14159 / 180) - 30, hueCircleR - hueCircleR * sin(150 * 3.14159 / 180) - 20);// 添加文字到场景scene->addItem(textItem1);scene->addItem(textItem2);scene->addItem(textItem3);scene->addItem(textItem4);scene->addItem(textItem5);scene->addItem(textItem6);
}

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

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

相关文章

移除链表元素数据结构oj题(力扣题206)

目录 题目描述&#xff1a; 题目解读&#xff08;分析&#xff09; 解决代码 题目描述&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 题目解读&#xff08;分析&#…

GLPK(GNU线性规划工具包)中建模语言MathProg的使用

GNU MathProg是一种用于描述线性数学规划模型的建模语言。用GNU MathProg语言编写的模型描述由一组语句和数据块组成。 在MathProg中&#xff0c;模型以集合、参数、变量、约束和目标(sets, parameters, variables, constraints, objectives称为模型对象)的形式进行描述。 在Ma…

《Python星球日记》 第77天:模型部署与总结

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、模型部署技术1. 模型文件导出不同模型格式对比2. 使用Flask构建RESTful API3. 使用FastAPI构建高性能API4. 部署优化与最佳实践二、部署架构…

【JavaWeb】MySQL(准备篇)

1 MySQL安装 1.1 解压 下载完成后我们得到的是一个压缩包&#xff08;所有文件均在文末安装包中&#xff09;&#xff0c;将其解压&#xff0c;我们就可以得到MySQL 8.0.34 的软件本体了(就是一个文件夹)&#xff0c;我们可以把它放在你想安装的位置 。 1.2 配置 1.2.1 配置…

国产数据库工具突围:SQLynx如何解决Navicat的三大痛点?深度体验报告

引言&#xff1a;Navicat的"中国困境" 当开发者面对达梦数据库的存储过程调试&#xff0c;或是在人大金仓中处理复杂查询时&#xff0c;Navicat突然变得力不从心——这不是个例。 真实痛点&#xff1a;某政务系统迁移至OceanBase后&#xff0c;开发团队发现Navicat无…

ETL数据集成产品选型需要关注哪些方面?

ETL&#xff08;Extract&#xff0c;Transform&#xff0c;Load&#xff09;工具作为数据仓库和数据分析流程中的关键环节&#xff0c;其选型对于企业的数据战略实施有着深远的影响。谷云科技在 ETL 领域耕耘多年&#xff0c;通过自身产品的实践应用&#xff0c;对 ETL 产品选型…

数据结构实验10.1:内部排序的基本运算

文章目录 一&#xff0c;实验目的二&#xff0c;实验内容1. 数据生成与初始化2. 排序算法实现&#xff08;1&#xff09;直接插入排序&#xff08;2&#xff09;二分插入排序&#xff08;3&#xff09;希尔排序&#xff08;4&#xff09;冒泡排序&#xff08;5&#xff09;快速…

从秒开到丝滑体验!WebAssembly助力ZKmall商城重构 B2B2C 商城性能基线

在 B2B2C 电商领域&#xff0c;用户对页面加载速度与交互流畅度的要求日益严苛。传统 Web 技术在处理复杂业务逻辑、海量数据渲染时&#xff0c;常出现卡顿、延迟等问题&#xff0c;导致用户流失。ZKmall 商城创新性地引入 WebAssembly&#xff08;简称 Wasm&#xff09;技术&a…

FD+Mysql的Insert时的字段赋值乱码问题

方法一 FDQuery4.SQL.Text : INSERT INTO 信息表 (中心, 分组) values(:中心,:分组); FDQuery4.Params[0].DataType : ftWideString; //必须加这个数据类型的定义&#xff0c;否则会有乱码 FDQuery4.Params[1].DataType : ftWideString; //ftstring就不行&#xff0c;必须是…

vue2.0 组件生命周期

个人简介 &#x1f468;‍&#x1f4bb;‍个人主页&#xff1a; 魔术师 &#x1f4d6;学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全栈发展 &#x1f6b4;个人状态&#xff1a; 研发工程师&#xff0c;现效力于政务服务网事业 &#x1f1e8;&#x1f1f3;人生格言&…

使用GmSSL v3.1.1实现SM2证书认证

1、首先使用gmssl命令生成根证书、客户端公私钥&#xff0c;然后使用根证书签发客户端证书&#xff1b; 2、然后编写代码完成认证功能&#xff0c;使用根证书验证客户端证书是否由自己签发&#xff0c;然后使用客户端证书验证客户端私钥对随机数的签名是否正确。 第一部分生成根…

升级mysql (rpm安装)

#备份以防万一 备份配置文件: /etc/my.cnf.d/server.cnf 备份数据: mysqldump -u your_username -p --all-databases > all_databases.sql #停止 systemctl stop mysql #卸载旧版 yum remove mariadb #安装新版( 通过yum安装报错,死活安装不了,只能rpm安装) 下载地址…

深入理解pip:Python包管理的核心工具与实战指南

# 深入理解pip&#xff1a;Python包管理的核心工具与实战指南 在Python开发中&#xff0c;第三方库是提升效率的关键。而pip作为Python官方的包管理工具&#xff0c;承担着安装、卸载、升级和管理库的重要职责。本文将全面解析pip的核心命令&#xff0c;结合实例演示用法&#…

Linux配置SSH密钥认证

介绍 配置SS秘钥认证后&#xff0c;可以通过shell脚本免密删除文件或执行命令。 # 生成密钥对&#xff08;如果还没有&#xff09; ssh-keygen -t rsa# 将公钥复制到服务器 ssh-copy-id "$remote_user$remote_host"

python打卡第30天

知识点回顾&#xff1a; 一&#xff0c;导入官方库的三种手段。 使用 import 直接导入整个模块 import module_name 使用 from ... import ... 导入特定功能 from module_name import function_name 使用 as 关键字重命名模块或功能 import module_name as alias # 或 from mod…

Java基础(网络编程)

一、概述 目的&#xff1a;网络通信&#xff1a; 1、设备和设备 2、进程和进程 1&#xff09;不同设备之间 2&#xff09;本地设备之间 需要解决的问题&#xff1a; 如何准确地发送到对方的主机 - IP地址 - 唯一的定位网络中的一台主机 如何准确的发送到对方主机的进程 -…

第二届parloo杯的RSA_Quartic_Quandary

&#xff08;害&#xff0c;还是太菜了&#xff0c;上去秒了一道题之后就动不了了&#xff0c;今晚做个记录&#xff0c;一点点的往回拾起吧&#xff09; # from Crypto.Util.number import getPrime, bytes_to_long # import math # # FLAG b************** # # # def gene…

RLᵛ_ Better Test-Time Scaling by Unifying LLM Reasoners With Verifiers

RLᵛ: Better Test-Time Scaling by Unifying LLM Reasoners With Verifiers 在人工智能领域&#xff0c;大语言模型&#xff08;LLM&#xff09;的推理能力提升一直是研究热点。今天要解读的论文提出了一种全新的强化学习框架RLᵛ&#xff0c;通过融合推理与验证能力&#xf…

VS中将控制台项目编程改为WINDOWS桌面程序

有时候因为误操作&#xff0c;建立了控制台项目&#xff0c;但是实际上想建立桌面程序。那么应该如何改过来呢&#xff1f; 一共要修改两个地方&#xff0c;修改步骤如下&#xff1a; 第一处修改地点&#xff1a; 将C/C下面的预处理器选项中&#xff0c;将原本的_CONSOLE修改…

API Gateway REST API 集成 S3 服务自定义 404 页面

需求分析 使用 API Gateway REST API 可以直接使用 S3 作为后端集成对外提供可以访问的 API. 而当访问的 URL 中存在无效的桶, 或者不存在的对象时, API Gateway 默认回向客户端返回 200 状态码. 而实际上这并不是正确的响应, 本文将介绍如何自定义返回 404 错误页面. 基本功…