使用 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.pswp.cn/pingmian/81579.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81579.shtml
英文地址,請注明出處:http://en.pswp.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 錯誤頁面. 基本功…