qt繪制餅狀圖并實現點擊即放大點擊部分

做得比較low

#ifndef TEST_POWER_H
#define TEST_POWER_H#include <QWidget>
#include <QtMath>
#include <QPainter>
#include <QPushButton>
#include <QVector>
#include <cmath>namespace Ui {
class test_power;
}
struct PieData
{QString name;   //名稱int num;        //數量QColor color;   //顏色PieData(QString name,int num,QColor color){this->name = name;this->num = num;this->color = color;}
};struct shanxing{double zhanbi;double start_x;double start_y;double end_x;double end_y;
};class test_power : public QWidget
{Q_OBJECTpublic:explicit test_power(int dongli=0,int zhaoming=0,int kongtiao=0,int teshu=0,int clicked=1000,QWidget *parent = nullptr);~test_power();QVector<QPointF> a;int m_proportion[4],clicked_code;void initWidget();//圓環圖各參數函數接口void setRadiusLong(int radius_long);void setRadius(int radius);void setInnerWidth(int width);void setCenter(QPoint center);void setStartAngle(qreal startAngle);void setTextDistance(int textDistance);void setPieData(QVector<PieData> vData);void refreshChart();shanxing my_shanxing[4];int m_radius,m_radius_long;         //外圓半徑int m_innerWidth;     //圓環內徑QPoint m_center;      //圓心坐標qreal m_startAngle;   //圓環繪制起點int m_textDistance;   //文本與圓心的距離qreal m_totality;     //總數QVector<PieData> m_vData;   //數據容器QPointF getArcPoint(const QPoint &center, int radius, double angle);void calculateArcPoints(QPainter &painter, const QPoint &center, int radius, double startAngle, double sweepLength,int i);
protected:void paintEvent(QPaintEvent *);void mousePressEvent(QMouseEvent *event);
private slots:
//    void on_pb_test_clicked();
//    void pb_clicked();
private:Ui::test_power *ui;
signals:
//傳出你想要傳出的參數void notice_clicked(int);};#endif // TEST_POWER_H
#include "test_power.h"
#include "ui_test_power.h"
#include <QDebug>
#include <QMouseEvent>test_power::test_power(int dongli,int zhaoming,int kongtiao,int teshu,int clicked,QWidget *parent) :QWidget(parent),ui(new Ui::test_power)
{ui->setupUi(this);setAttribute(Qt::WA_DeleteOnClose);setWindowFlags(Qt::FramelessWindowHint);this->initWidget();m_proportion[0] = dongli;m_proportion[1] = zhaoming;m_proportion[2] = kongtiao;m_proportion[3] = teshu;clicked_code = clicked;//設置圓環各參數this->setRadius(160);this->setRadiusLong(190);this->setInnerWidth(0);   //設為0即為餅圖this->setCenter(QPoint(275,275));this->setStartAngle(0);   //區域繪制方向為逆時針this->setTextDistance(210);this->refreshChart();
}test_power::~test_power()
{delete ui;
}//初始化界面
void test_power::initWidget()
{//初始化變量m_radius = 0;m_radius_long=0;m_innerWidth = 0;m_center = QPoint(0,0);m_startAngle = 0;m_textDistance = 0;m_totality = 0;m_vData.clear();
}
//設置外圓長半徑
void test_power::setRadiusLong(int radius_long)
{m_radius_long=radius_long;
}
//設置外圓半徑
void test_power::setRadius(int radius)
{m_radius = radius;
}//設置圓環內徑
void test_power::setInnerWidth(int width)
{m_innerWidth = width;
}//設置圓心
void test_power::setCenter(QPoint center)
{m_center = center;
}//設置圓環繪制起點
void test_power::setStartAngle(qreal startAngle)
{m_startAngle = startAngle;
}//設置文本與圓心的距離
void test_power::setTextDistance(int textDistance)
{m_textDistance = textDistance;
}//設置餅圖數據
void test_power::setPieData(QVector<PieData> vData)
{//獲取數據m_vData = vData;//獲取總數m_totality = 0;for(int i=0;i<m_vData.size();i++){m_totality += m_vData[i].num;}this->update();
}//更新餅圖
void test_power::refreshChart()
{//設置圓環圖各區域數據名稱及顏色QVector<PieData> vData;QColor m_colors[4] = {QColor(237,117,57),QColor(111,173,30),QColor(198,49,16),QColor(248,206,34)};QString m_names[4] = {"quyu1","quyu2","quyu3","quyu4"};for(int i=0;i<4;i++){if(!m_names[i].isEmpty() && m_proportion[i]>0){PieData data = PieData(QString("%1\n%2").arg(m_names[i]).arg(QString::number(m_proportion[i])+"%"),m_proportion[i],m_colors[i]);vData.push_back(data);}}this->setPieData(vData);
}//重寫繪圖事件
void test_power::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing,true);   //抗鋸齒//繪制圓角背景painter.setBrush(Qt::transparent);painter.setPen(Qt::NoPen);   //去除背景邊框painter.drawRoundedRect(10,10,360,360,8,8);//繪制餅圖qreal startAngle = m_startAngle;   //繪制起點qreal spanAngle = 0;   //各區域占比,覆蓋角度for(int i=0;i<m_vData.size();i++){painter.setPen(m_vData[i].color);painter.setBrush(m_vData[i].color);if(m_totality)   //防止總數為0{spanAngle = m_vData[i].num * 360 / m_totality;my_shanxing[i].zhanbi = m_vData[i].num / m_totality;}if(i==clicked_code){painter.drawPie(m_center.x() - m_radius_long,m_center.y() - m_radius_long,m_radius_long * 2,m_radius_long * 2,startAngle * 16,spanAngle * 16);}else{painter.drawPie(m_center.x() - m_radius,m_center.y() - m_radius,m_radius * 2,m_radius * 2,startAngle * 16,spanAngle * 16);}calculateArcPoints(painter, m_center,m_radius,startAngle,spanAngle,i);startAngle += spanAngle;}//繪制區域名稱和占比startAngle = m_startAngle;spanAngle = 0;for(int i=0;i<m_vData.size();i++){painter.setPen(QColor("#ffffff"));painter.setFont(QFont("STSongti-SC-Bold, STSongti-SC",16));if(m_totality){spanAngle = m_vData[i].num * 360 / m_totality;}int textAngle = startAngle + spanAngle / 2;QString text = QString("%1").arg(m_vData[i].name);int textWidth = painter.fontMetrics().horizontalAdvance(text);int textHeight = painter.fontMetrics().height();int textX = m_center.x() + m_textDistance * qCos(textAngle * M_PI / 180) - textWidth / 2;int textY = m_center.y() - m_textDistance * qSin(textAngle * M_PI / 180) + textHeight / 2;startAngle += spanAngle;//繪制文本QRect rect(textX,textY - textHeight,textWidth + 10,textHeight * 2);painter.drawText(rect,Qt::AlignCenter,text);//繪制連接線,文本要靠近對應區域,需要修改連接線終點位置painter.setPen(m_vData[i].color);int lineStartX = m_center.x() + (m_radius - 10) * qCos(textAngle * M_PI / 180);int lineStartY = m_center.y() - (m_radius - 10) * qSin(textAngle * M_PI / 180);int lineEndX = 0;int lineEndY = 0;if(textX < lineStartX)   //文本在左邊{//可自行根據實際進行位置偏移的修改lineEndX = textX + textWidth/2;if(textY < lineStartY)   //文本在上邊{lineEndY = textY + textHeight + 5;}else{lineEndY = textY - textHeight - 5;}}else{lineEndX = textX + textWidth/2;if(textY < lineStartY){lineEndY = textY;}else{lineEndY = textY - textHeight - 5;}}painter.drawLine(lineStartX,lineStartY,lineEndX,lineEndY);//繪制終點painter.setPen(QPen(m_vData[i].color,5));painter.drawPoint(lineEndX,lineEndY);//將終點設為空心圓//painter.drawEllipse(QPoint(lineEndX,lineEndY),5,5);//painter.setPen(QPen(QColor("#FFFFFF"),1));//painter.setBrush(QColor("#FFFFFF"));//painter.drawEllipse(QPoint(lineEndX,lineEndY),3,3);}//繪制內圓,將餅圖變為圓環painter.setPen(QPen(QColor("#FFFFFF"),10));painter.setBrush(QColor("#FFFFFF"));painter.drawEllipse(m_center,m_innerWidth,m_innerWidth);
}void test_power::mousePressEvent(QMouseEvent *event)
{QPoint mousePos = event->pos();double x = mousePos.x()- m_center.x();if(x==0){return;}double y =  m_center.y() - mousePos.y();if(y==0){return;}if(  x*x + y*y < m_radius*m_radius){// 輸出或使用坐標點
//        qDebug() << "Mouse pressed at position:" << x << "," << y;if(x>0 && y>0 ){double zhanbi=0;for (int i=0;i<4;i++){zhanbi += my_shanxing[i].zhanbi;if(zhanbi<0.25 && y/x>my_shanxing[i].start_y/my_shanxing[i].start_x && y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}if(zhanbi>=0.25) {qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}}else if(x<0 && y>0 ){double zhanbi=0;for (int i=0;i<4;i++){zhanbi += my_shanxing[i].zhanbi;if(zhanbi>0.25 && zhanbi<=0.5){if(my_shanxing[i].start_x>=0){//起始位置在第一象限if(y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}else{//起始位置在第二象限if(y/x>my_shanxing[i].start_y/my_shanxing[i].start_x && y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}}if(zhanbi>0.5) {qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}}else if(x<0 && y<0 ){double zhanbi=0;for (int i=0;i<4;i++){zhanbi += my_shanxing[i].zhanbi;if(zhanbi>0.5 && zhanbi<=0.75){if(my_shanxing[i].start_y>=0){//起始位置在第一或者第二象限if(y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;return;}}else{//起始位置在第三象限if(y/x>my_shanxing[i].start_y/my_shanxing[i].start_x && y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;return;}}}if(zhanbi>0.75) {qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}}else if(x>0 && y<0 ){double zhanbi=0;for (int i=0;i<4;i++){zhanbi += my_shanxing[i].zhanbi;if(zhanbi>0.75){if(my_shanxing[i].start_y>=0 || (my_shanxing[i].start_y<=0 && my_shanxing[i].start_x<=0)){//起始位置位于一或者二或者三象限if(y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}else{
//                        qDebug()<<"iiiiiiiiiiiiiiiiii="<<i<<"=="<<y/x<<"==="<<my_shanxing[i].start_y/my_shanxing[i].start_x<<"------"<<my_shanxing[i].end_y/my_shanxing[i].end_x;
//                        qDebug()<<i<<"==y="<<y<<"   x="<<x<<"===y="<<my_shanxing[i].start_y<<"===x"<<my_shanxing[i].start_x<<"------y="<<my_shanxing[i].end_y<<"   x="<<my_shanxing[i].end_x;if(y/x>my_shanxing[i].start_y/my_shanxing[i].start_x && y/x<my_shanxing[i].end_y/my_shanxing[i].end_x){qDebug()<<"clicked ============"<<i;emit notice_clicked(i);return;}}}}}}
}void test_power::calculateArcPoints(QPainter &painter, const QPoint &center, int radius, double startAngle, double sweepLength,int inum) {QPointF startPoint = getArcPoint(center, radius, startAngle);QPointF endPoint = getArcPoint(center, radius, startAngle + sweepLength);my_shanxing[inum].start_x=startPoint.x()-m_center.x();my_shanxing[inum].start_y= m_center.y()-startPoint.y();my_shanxing[inum].end_x= endPoint.x()-m_center.x();my_shanxing[inum].end_y= m_center.y()-endPoint.y();// 這里可以處理startPoint和endPoint,例如繪制線條或進行其他操作
//     painter.drawLine(startPoint, endPoint); // 示例:繪制扇形邊界線
//     qDebug()<<"startPoint x="<<my_shanxing[inum].start_x<<"    y="<<my_shanxing[inum].start_y;
//     qDebug()<<"endPoint x="<<my_shanxing[inum].end_x<<"    y="<<my_shanxing[inum].end_y;}QPointF test_power::getArcPoint(const QPoint &center, int radius, double angle) {double radian = angle * M_PI / 180; // 將角度轉換為弧度return QPointF(center.x() + radius * cos(radian), center.y() - radius * sin(radian));}

在這里插入圖片描述
ui里面就很簡單只要設置尺寸就行了

調用時候的代碼
//加載餅狀圖
dongli=20;zhaoming=30;kongtiao=40;teshu=20;
my_test_power = new test_power(dongli,zhaoming,kongtiao,teshu);
connect(my_test_power,SIGNAL(notice_clicked(int)),this,SLOT(refresh_power(int)));
test_power_list.append(my_test_power);
glayout_power = new QVBoxLayout();
glayout_power->addWidget(my_test_power);
ui->frame->setLayout(glayout_power);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88246.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88246.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88246.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HashMap的put、get方法詳解(附源碼)

put方法 HashMap 只提供了 put 用于添加元素&#xff0c;putVal 方法只是給 put 方法調用的一個方法&#xff0c;并沒有提供給用戶使用。 對 putVal 方法添加元素的分析如下&#xff1a;如果定位到的數組位置沒有元素 就直接插入。如果定位到的數組位置有元素就和要插入的 key …

雙立柱式帶鋸床cad【1張總圖】+設計說明書+絳重

雙立柱式帶鋸床 摘 要 隨著機械制造技術的進步&#xff0c;制造業對于切割設備的精度、效率和穩定性要求越來越高。雙立柱式帶鋸床作為一種重要的切割設備&#xff0c;必須能夠滿足工業生產對于高精度、高效率的需求。 雙立柱式帶鋸床是一種重要的工業切割設備&#xff0c;其結…

在線JS解密加密配合ECC保護

在線JS解密加密配合ECC保護 1. ECC加密簡介 定義 ECC&#xff08;Elliptic Curve Cryptography&#xff09;是一種基于橢圓曲線數學的公鑰加密技術&#xff0c;利用橢圓曲線離散對數問題&#xff08;ECDLP&#xff09;實現高安全性。 背景 1985年&#xff1a;Koblitz&#xff0…

使用 Docker Compose 簡化 INFINI Console 與 Easysearch 環境搭建

前言回顧 在上一篇文章《搭建持久化的 INFINI Console 與 Easysearch 容器環境》中&#xff0c;我們詳細介紹了如何使用基礎的 docker run 命令&#xff0c;手動啟動和配置 INFINI Console (1.29.6) 和 INFINI Easysearch (1.13.0) 容器&#xff0c;并實現了關鍵數據的持久化&…

Word 怎么讓段落對齊,行與行之間寬一點?

我們來分兩步解決&#xff1a;段落對齊 和 調整行距。 這兩個功能都集中在Word頂部的【開始】選項卡里的【段落】區域。 第一步&#xff1a;讓段落對齊 “對齊”指的是段落的左右邊緣如何排列。通常有四種方式。 操作方法&#xff1a;將鼠標光標點在你想修改的那個段落里的任意…

Attention機制完全解析:從原理到ChatGPT實戰

一、Attention的本質與計算步驟 1.1 核心思想 動態聚焦&#xff1a;Attention是一種信息分配機制&#xff0c;讓模型在處理輸入時動態關注最重要的部分。類比&#xff1a;像人類閱讀時用熒光筆標記關鍵句子。 1.2 計算三步曲&#xff08;以"吃蘋果"為例&#xff09; …

2025年3月青少年電子學會等級考試 中小學生python編程等級考試三級真題答案解析(判斷題)

博主推薦 所有考級比賽學習相關資料合集【推薦收藏】1、Python比賽 信息素養大賽Python編程挑戰賽 藍橋杯python選拔賽真題詳解

HTML5 新特性詳解:從語義化到多媒體的全面升級

很多小伙伴本都好奇&#xff1a;HTML5有什么功能是以前的HTML沒有的&#xff1f; 今天就給大家說道說道 HTML5 作為 HTML 語言的新一代標準&#xff0c;帶來了諸多革命性的新特性。這些特性不僅簡化了前端開發流程&#xff0c;還大幅提升了網頁的用戶體驗和功能性。本文將深入…

mac安裝docker

1、下載docker-desktop https://www.docker.com/products/docker-desktop/2、安裝&#xff0c;雙擊安裝 3、優化docker配置 默認配置 cat ~/Library/Group\ Containers/group.com.docker/settings-store.json {"AutoStart": false,"DockerAppLaunchPath": …

mapbox進階,繪制不隨地圖旋轉的矩形,保證矩形長寬沿屏幕xy坐標方位

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言1.1 ??mapboxgl.Map 地圖對象1.2 ??mapboxgl.Map style屬性1.3 ??line線圖層樣式1.4 ??circle點圖層樣…

${project.basedir}延申出來的Maven內置的一些常用屬性

如&#xff1a;${project.basedir} 是 Maven 的內置屬性&#xff0c;可以被 pom.xml 直接識別。它表示當前項目的根目錄&#xff08;即包含 pom.xml 文件的目錄&#xff09;。 Maven 內置的一些常用屬性&#xff1a; 項目相關&#xff1a; ${project.basedir} <!-- 項…

[特殊字符] Python 批量生成詞云:讀取詞頻 Excel + 自定義背景 + Excel to.png 流程解析

本文展示如何用 Python 從之前生成的詞頻 Excel 文件中讀取詞頻數據&#xff0c;結合 wordcloud 和背景圖&#xff0c;批量生成直觀美觀的詞云圖。適用于文本分析、內容展示、報告可視化等場景。 &#x1f4c2; 第一步&#xff1a;讀取所有 Excel 詞頻文件 import os from ope…

模擬網絡請求的C++類設計與實現

在C開發中&#xff0c;理解和模擬網絡請求是學習客戶端-服務器通信的重要一步。本文將詳細介紹一個模擬HTTP網絡請求的C類庫設計&#xff0c;幫助開發者在不涉及實際網絡編程的情況下&#xff0c;理解網絡請求的核心概念和工作流程。 整體架構設計 這個模擬網絡請求的類庫主要由…

移動機器人的認知進化:Deepoc大模型重構尋跡本質

統光電尋跡技術已逼近物理極限。當TCRT5000傳感器在強烈環境光下失效率超過37%&#xff0c;當PID控制器在路徑交叉口產生63%的決策崩潰&#xff0c;工業界逐漸意識到&#xff1a;導引線束縛的不僅是車輪&#xff0c;更是機器智能的演化可能性。 ?技術破局點出現在具身認知架構…

記錄一次pip安裝錯誤OSError: [WinError 32]的解決過程

因為要使用 PaddleOCR&#xff0c;需要安裝依賴。先通過 conda新建了虛擬環境&#xff0c;然后安裝 PaddlePaddle&#xff0c;繼續安裝 PaddleOCR&#xff0c;上述過程我是在 VSCode的終端中處理&#xff0c;結果報錯如下&#xff1a;Downloading multidict-6.6.3-cp312-cp312-…

后端id設置long類型時,傳到前端,超過19位最后兩位為00

文章目錄一、前言二、問題描述2.1、問題背景2.2、問題示例三、解決方法3.1、將ID轉換為字符串3.2、使用JsonSerialize注解3.3、使用JsonFormat注解一、前言 在后端開發中&#xff0c;我們經常會遇到需要將ID作為標識符傳遞給前端的情況。當ID為long類型時&#xff0c;如果該ID…

SpringAI學習筆記-MCP客戶端簡單示例

MCP客戶端是AI與外部世界交互的橋梁。在AI系統中&#xff0c;大模型雖然具備強大的認知能力&#xff0c;卻常常受限于數據孤島問題&#xff0c;無法直接訪問外部工具和數據源。MCP協議應運而生&#xff0c;作為標準化接口解決這一核心挑戰。該協議采用客戶端-服務端架構&#x…

postgresql|數據庫|系統性能監控視圖pg_stat與postgresql數據庫的調優(備忘)

一、 寫作初衷 通常,我們使用navicat這樣的數據庫圖形管理工具,只能看到用戶層面的表,視圖,而系統層面的表,視圖,函數是無法看到的,這些表,視圖和函數好像也可以稱之為內模式;而這些視圖,函數的作用是非常大的,其中pg_stat 族系統視圖可以得到數據庫的詳細運行信息…

網絡安全護網實戰:攻擊手段解析與防御策略

在網絡安全領域&#xff0c;護網行動中對各類攻擊方式和漏洞原理的掌握至關重要。本文將詳細解析常見的攻擊方式及其背后的漏洞原理&#xff0c;幫助大家提升護網技能。一、常見攻擊方式及漏洞原理1. SQL注入漏洞? 定義&#xff1a;將惡意的數據庫語句注入到后臺數據庫去執行&…

使用alist+RaiDrive+webdav將百度夸克網盤變為本地電腦磁盤方法教程

由于每天都要操作網盤不下十幾次&#xff0c;頻繁啟動網盤比較麻煩。 使用百度夸克網盤的webdav服務可以將百度夸克網盤掛載到本地電腦上&#xff0c;就像操作本地電腦硬盤一樣操作網盤&#xff0c;非常方便。我們以alistraidrive為例演示。 首先打開百度網盤pan.baidu.com&a…