QT使用QPainter绘制多边形维度图

        多边形统计维度图是一种用于展示多个维度的数据的图表。它通过将各个维度表示为图表中的多边形的边,根据数据的大小和比例来确定各个维度的长度。

一、简述

         本示例实现六边形战力统计维度图,一种将六个维度的战力统计以六边形图形展示的方法。六个维度是:攻击力、防御力、速度、智力、生命值、特殊能力。六边形战力统计维度图将这些维度以六个边长不等的六边形表示,每个边长代表对应维度的数值大小。通过连接这些边,可以得到一个多边形,多边形的形状和大小表示单位的整体战斗能力。一般来说,这个多边形越接近完整的六边形,说明单位在各项能力上都相对均衡和强大。

二、 设计思路        

        要实现多边形统计维度图,基类选择QWidget,使用QPainter根据图形需求画出图形。

设计思路:

  1. 将统计维度分别表示为顶点,分别标注在顶点上。这些统计维度可以根据具体需求进行选择,例如攻击力、防御力、速度等。

  2. 在多边形图的上,可以设置不同的刻度值,表示不同的水平。根据统计数据的大小,可以将数据点标注在相应的位置上。

  3. 使用不同的颜色或图案来表示不同的统计数据点,以便更好地区分不同的数据。

  4. 在多边形图的周围添加标签,用来说明各个统计维度的含义,以便用户更好地理解图表。

三、效果 

四、核心代码  
1、头文件
#ifndef DIMENSIONCHARTWIDGET_H
#define DIMENSIONCHARTWIDGET_H#include <QMap>
#include <QPen>
#include <QObject>
#include <QWidget>class DimensionInfo;
class DimensionChartWidget : public QWidget
{Q_OBJECTpublic:explicit DimensionChartWidget(QWidget *parent = nullptr);inline QColor backgroundColor() const { return m_backgroundColor; }inline void setBackgroundColor(const QColor &backgroundColor) { m_backgroundColor = backgroundColor; }inline float radius() const { return m_radius; }// 设置维度半径inline void setRadius(float radius) { m_radius = radius; }inline int sidesNumber() const { return m_sidesNumber; } // 设置维度网格数量inline void setSidesNumber(int sidesNumber) {m_sidesNumber = sidesNumber; }inline QPen sidesPen() const { return m_sidesPen; }// 设置维度网格画笔inline void setSidesPen(const QPen &sidesPen) { m_sidesPen = sidesPen; }inline QVector<DimensionInfo> dimensionInfos() const { return m_dimensionInfos; }inline void setDimensionInfos(const QVector<DimensionInfo> &dimensionInfos) { m_dimensionInfos = dimensionInfos; }inline QPen textPen() const { return m_textPen; }//设置字体画笔inline void setTextPen(const QPen &textPen) { m_textPen = textPen; }inline QPen dimensionPen() const { return m_dimensionPen; }// 设置维度画笔inline void setDimensionPen(const QPen &dimensionPen) { m_dimensionPen = dimensionPen; }inline QFont textFont() const { return m_textFont; }//设置字体inline void setTextFont(const QFont &textFont) { m_textFont = textFont; }inline int filletRadius() const { return m_filletRadius; }inline void setFilletRadius(int filletRadius) { m_filletRadius = filletRadius; }protected:void paintEvent(QPaintEvent*);void drawText(QPainter&, QPointF, QString text);void convertPoint(QPointF&);private:void init();private:QPen m_textPen;QPen m_sidesPen;QPen m_dimensionPen;QFont m_textFont;QColor m_backgroundColor;int m_filletRadius;float m_radius;int m_sidesNumber;QVector<DimensionInfo> m_dimensionInfos;
};class DimensionInfo {
public:DimensionInfo() = default;DimensionInfo(QString text, float percentage) { m_text = text; m_percentage = percentage; }inline QString text() const { return m_text; }inline void setText(const QString &text) { m_text = text; }inline float percentage() const { return m_percentage; }inline void setPercentage(float percentage) { m_percentage = percentage; }private:QString m_text;float m_percentage;
};
#endif // DIMENSIONCHARTWIDGET_H
2、实现代码
#include "DimensionChartWidget.h"
#include <QPainter>
#include <QtMath>
#include <QPainterPath>DimensionChartWidget::DimensionChartWidget(QWidget *parent) : QWidget(parent)
{m_radius = 0;m_sidesNumber = 1;init();
}void DimensionChartWidget::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(QColor(m_backgroundColor));painter.setBrush(QBrush(m_backgroundColor));painter.drawRoundedRect(rect(), m_filletRadius, m_filletRadius);// 绘图设备的坐标原点(0,0)在左上角,水平向右增长,垂直向下增长。// 将坐标系原点移动到界面中间painter.translate(width() / 2.0, height() / 2.0);// 设中心点到边的垂线与半径的夹角为degree=(360/count)/2float degree = 360.0 / m_dimensionInfos.size();// 开始绘制多边形,并为每个区域上色painter.setPen(m_sidesPen);QPointF lastPoint(0, -m_radius);QVector<QPointF> points;for(int i = 0; i < m_dimensionInfos.size(); i++){float radian = qDegreesToRadians(degree * (i + 1));float x = m_radius * qSin(radian);float y = m_radius * qCos(radian);// 绘制该三角区块QPainterPath path;QPointF point(x, -y);path.lineTo(point);path.lineTo(lastPoint);path.lineTo(0, 0);painter.drawPath(path);//  绘制内线for(int j = m_sidesNumber - 1; j > 0; j--){float multiple = (float)j / m_sidesNumber;painter.drawLine(point * multiple, lastPoint * multiple);}// 绘制文本painter.save();painter.setPen(m_textPen);painter.setFont(m_textFont);drawText(painter, point, m_dimensionInfos.at(i).text());painter.restore();lastPoint = point;points << point * m_dimensionInfos.at(i).percentage();}// 绘制维度信息painter.setPen(m_dimensionPen);QColor color = m_dimensionPen.color();color.setAlpha(150);painter.setBrush(QBrush(color));QPolygonF polygon(points);QPainterPath painterPath;painterPath.addPolygon(polygon);painter.drawPolygon(polygon);
}//绘制文本
void DimensionChartWidget::drawText(QPainter& painter, QPointF point, QString text)
{convertPoint(point);QRectF textRect;textRect.setSize(QSize(50, 30));int flag = Qt::AlignCenter;if(point.x() > 0){if(point.y() < 0){//x > 0 y < 0textRect.setBottomLeft(point);textRect.setTopRight(QPoint(point.x() + 50, point.y() - 30));flag = Qt::AlignBottom | Qt::AlignLeft;}else if(point.y() > 0){//x>0 y>0textRect.setTopLeft(point);textRect.setBottomRight(QPoint(point.x() + 50, point.y() + 30));flag = Qt::AlignTop | Qt::AlignLeft;}else{//x>0 y=0point.setY(point.y() - 15);textRect.setTopLeft(point);textRect.setBottomRight(QPoint(point.x() + 50, point.y() + 30));flag = Qt::AlignVCenter | Qt::AlignLeft;}}else if(point.x() < 0){if(point.y() < 0){//x<0 y<0textRect.setBottomRight(point);textRect.setTopLeft(QPoint(point.x() - 50, point.y() - 30));flag = Qt::AlignBottom | Qt::AlignRight;}else if(point.y() > 0){//x<0 y>0textRect.setTopRight(point);textRect.setBottomLeft(QPoint(point.x() - 50, point.y() + 30));flag = Qt::AlignTop | Qt::AlignRight;}else{//x<0 y=0point.setY(point.y() - 15);textRect.setTopRight(point);textRect.setBottomLeft(QPoint(point.x() - 50, point.y() + 30));flag = Qt::AlignVCenter | Qt::AlignRight;}}else{if(point.y() < 0){//x=0 y<0point.setX(point.x() - 25);textRect.setBottomRight(point);textRect.setTopLeft(QPoint(point.x() + 50, point.y() - 30));flag = Qt::AlignHCenter | Qt::AlignBottom;}else if(point.y() > 0){//x=0 y>0point.setX(point.x() - 25);textRect.setTopLeft(point);textRect.setBottomRight(QPoint(point.x() + 50, point.y() + 30));flag = Qt::AlignHCenter | Qt::AlignTop;}}painter.drawText(textRect, flag, text);
}void DimensionChartWidget::convertPoint(QPointF& point)
{if(qAbs(point.x()) < 0.001){point.setX(0);}else if(qAbs(point.y()) < 0.001){point.setY(0);}
}void DimensionChartWidget::init()
{setBackgroundColor(QColor(255,255,255));// 设置维度网格数量setSidesNumber(5);// 设置维度半径setRadius(120);// 设置维度网格画笔QPen sidesPen;sidesPen.setColor(QColor("#0095C5"));sidesPen.setWidth(2);setSidesPen(sidesPen);// 设置维度画笔QPen dimensionPen;dimensionPen.setColor(Qt::GlobalColor::red);dimensionPen.setWidth(3);setDimensionPen(dimensionPen);// 设置字体信息QPen textPen;setTextPen(textPen);QFont textFont;textFont.setFamily("微软雅黑");textFont.setPointSize(10);setTextFont(textFont);
}

        以上是多边形统计维度图实现代码,在实际使用中,可以根据需要进行扩展,添加一些其他的功能。例如:

  1. 支持多边形的操作。使其支持多边形的旋转、平移、缩放等操作,以方便更灵活地对多边形进行分析和展示。

  2. 导入和导出多边形数据。我们可以添加文件读写功能,允许用户从外部文件导入多边形数据,并将统计维度的结果保存到文件中。

        这些功能的添加可以进一步提升多边形统计维度图的实用性和灵活性。根据具体的需求,你可以根据需要修改绘制参数和数据来自定义图形,可以选择扩展代码的功能,以适应不同的应用场景。      

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include "DimensionChartWidget.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{setWindowTitle("维度图");resize(400, 400);DimensionChartWidget* pDimensionChartWidget = new DimensionChartWidget(this);pDimensionChartWidget->resize(this->width() - 60, this->height() -60);pDimensionChartWidget->move(30, 30);QVector<DimensionInfo> dimensionInfos;DimensionInfo dimensionInfo("攻击力", 0.55);dimensionInfos.append(dimensionInfo);dimensionInfo.setText("防御力");dimensionInfo.setPercentage(0.85);dimensionInfos.append(dimensionInfo);dimensionInfo.setText("速度");dimensionInfo.setPercentage(0.95);dimensionInfos.append(dimensionInfo);dimensionInfo.setText("智力");dimensionInfo.setPercentage(0.45);dimensionInfos.append(dimensionInfo);dimensionInfo.setText("生命值");dimensionInfo.setPercentage(0.65);dimensionInfos.append(dimensionInfo);dimensionInfo.setText("特殊能力");dimensionInfo.setPercentage(0.65);dimensionInfos.append(dimensionInfo);pDimensionChartWidget->setDimensionInfos(dimensionInfos);
}MainWindow::~MainWindow()
{}

        以上示例是一个六边形战力统计维度图,可以用于综合评估某个实体在不同维度上的战力表现。通过提供各个维度的评分和连接评分最高点的边界来展示实体在不同维度上的能力表现。这样的图表可以帮助决策者更全面地了解和比较实体的战力,从而做出更准确的决策。

        谢谢您的关注和阅读!如有任何问题或需要帮助,请随时与我联系。希望您能继续支持并享受更多精彩的内容。祝您生活愉快!

六、源代码下载

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

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

相关文章

怎样在 PostgreSQL 中优化对复合索引的选择性?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中优化对复合索引的选择性一、理解复合索引的概念二、选择性的重要性三、优化复合索…

shell脚本-linux如何在脚本中远程到一台linux机器并执行命令

需求&#xff1a;我们需要从11.0.1.17远程到11.0.1.16上执行命令 实现&#xff1a; 1.让11.0.1.17 可以免密登录到11.0.1.16 [rootlocalhost ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created d…

【问题记录】Docker配置mongodb副本集实现数据流实时获取

配置mongodb副本集实现数据流实时获取 前言操作步骤1. docker拉取mongodb镜像2. 连接mongo1镜像的mongosh3. 在mongosh中初始化副本集 注意点 前言 由于想用nodejs实现实时获取Mongodb数据流&#xff0c;但是报错显示需要有副本集的mongodb才能实现实时获取信息流&#xff0c;…

27.js实现鼠标拖拽

e.offsetX是鼠标距离准确事件源的左上角距离 e.clientX是鼠标距离浏览器可视窗口左上角的距离 e.pageX是鼠标距离文档左上角的距离 /* 当鼠标点击div时开始挪动&#xff0c;当鼠标抬起&#xff0c;div静止——事件源是div 当鼠标点击后,鼠标在移动——事件源…

SpringCache介绍

SpringCache是Spring提供的缓存框架。提供了基于注解的缓存功能。 SpringCache提供了一层抽象&#xff0c;底层可以切换不同的缓存实现&#xff08;只需要导入不同的Jar包即可&#xff09;&#xff0c;如EHCache&#xff0c;Caffeine&#xff0c;Redis。 2个重要依赖已经导入&a…

简单一阶滤波器设计:matlab和C实现

一、简单一阶滤波器的模型 二、示例 得: y(n)-0.9y(n-1)=x(n)+0.05x(n-1),即:y(n)=0.9y(n-1)+x(n)+0.05x(n-1) 已知:,并且有: A. 假设输入序列有N=100个点 B. 系统初始状态为0,即y(-1)=0 C. 输入序列是因果序列,

【OpenRecall】超越 Windows Recall,OpenRecall 为你的隐私和自由而战

引言 随着 Windows 11 的 Recall 功能推出&#xff0c;我们看到了数字记忆回顾的全新可能性。然而&#xff0c;这项功能受限于特定的硬件——Copilot 认证的 Windows 硬件&#xff0c;并且仅在 Windows 平台上可用。对于追求隐私和硬件灵活性的用户来说&#xff0c;这无疑是个…

长按加速- 解决react - setInterval下无法更新问题

最开始直接setInterval里&#xff0c;useState硬写&#xff0c;发现更新不&#xff0c;固定值 换let&#xff0c;发现dom更新不了 正确做法是用ref 并且pc端可以长按的&#xff0c;只是要用onTouchStart&#xff0c;不要用onMouseDown onTouchStart{handleMouseDown} onTou…

在设计电气系统时,电气工程师需要考虑哪些关键因素?

在设计电气系统时&#xff0c;电气工程师需要考虑多个关键因素&#xff0c;以确保系统的安全性、可靠性、效率和经济性。我收集归类了一份plc学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向编程教学、问题视频讲解、毕设800套和语言…

word 设置多级混合标题自动更新

目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 有没有体会过多级标题&#xff0c;怎么设置都不听使唤的情况&#xff1f; 我想要的格式是&#xff1a; 二、原因分析 多级标题中发现&#xff0c;输入编号格式这里有个数字没有底纹,是了&#xff0…

系统架构设计师教程 第3章 信息系统基础知识-3.1 信息系统概述

系统架构设计师教程 第3章 信息系统基础知识-3.1 信息系统概述 3.1.1 信息系统的定义3.1.1.1 信息系统3.1.1.2 信息化3.1.2 信息系统的发展3.1.2.1 初始阶段3.1.2.2 传播阶段3.1.2.3 控制阶段3.1.2.4 集成阶段3.1.2.5 数据管理阶段3.1.2.6 成熟阶段3.1.3 信息系统的分类3.…

Redis-基础概念

目录 概念 Redis是什么 Redis 和 MySQL 的区别&#xff1f; Redis单线程有什么极端场景的瓶颈 Redis为什么快? 为什么Redis是单线程? Redis是单线程还是多线程 Redis为什么选择单线程做核心处理 Redis6.0之后引入了多线程&#xff0c;你知道为什么吗? 瓶颈是内存和I…

C#进阶-基于.NET Framework 4.x框架实现ASP.NET WebForms项目IP拦截器

在这篇文章中&#xff0c;我们将探讨如何在 ASP.NET WebForms 中实现IP拦截器&#xff0c;以便在 ASMX Web 服务方法 和 HTTP 请求 中根据IP地址进行访问控制。我们将使用自定义的 SoapExtension 和 IHttpModule 来实现这一功能&#xff0c;并根据常用的两种文本传输协议&#…

大模型“重构”教育:解构学习奥秘,推动教育普惠

大模型“重构”千行百业系列选题 生成式人工智能的热潮&#xff0c;为AI领域的发展注入新的活力&#xff0c;而“赋能千行百业”已经成为人们普遍对于人工智能和大模型的全新理解。 人工智能和大模型技术的迅猛发展正在以前所未有的速度深刻改变着各个行业。正如专家所预测&a…

【Apache POI】Java解析Excel文件并处理合并单元格-粘贴即用

同为牛马&#xff0c;点个赞吧&#xff01; 一、Excel文件样例 二、工具类源码 import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbookFactory; import org.springframework.web.multip…

windows实现自动化按键

1.选择目标窗口 获取窗口句柄 void KeyPresser::selectWindow() {SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);selectedWindowLabel->setText("请点击目标窗口..."); }void CALLBACK …

ZStack Cloud 5.1.8正式发布

2024年7月5日&#xff0c;ZStack Cloud正式发布最新版本——ZStack Cloud 5.1.8&#xff0c;涵盖一系列重要功能&#xff0c;以下为您进行详细介绍。 亮点速览 GPU运维管理增强&#xff1a;新增GPU设备统一管理界面&#xff1b;支持GPU工作状态和实时负载监控报警三层网络运维…

套用BI方案做数据可视化是种什么体验?

在数字化转型的浪潮中&#xff0c;数据可视化作为连接数据与决策的桥梁&#xff0c;其重要性日益凸显。近期&#xff0c;我有幸体验了奥威BI方案进行数据可视化的全过程&#xff0c;这不仅是一次技术上的探索&#xff0c;更是一次对高效、智能数据分析的深刻感受。 初识奥威&a…

嵌入式物联网在教育行业的应用——案例分析

作者主页: 知孤云出岫 嵌入式物联网在教育行业的应用——案例分析 目录 作者主页:嵌入式物联网在教育行业的应用——案例分析一、引言二、智能教室&#xff1a;环境监测系统1. 硬件需求2. 电路连接3. 代码实现 三、个性化学习&#xff1a;智能学习平台1. 数据处理与分析2. 代…

从零开始学量化~Ptrade使用教程(六)——盘后定价交易、港股通与债券通用质押式回购

盘后固定价交易 实现科创板、创业板的盘后固定价交易&#xff0c;界面如下显示&#xff1a; 交易 输入科创板或创业板代码&#xff0c;选择委托方向&#xff0c;输入委托价格、委托数量&#xff0c;点击“买入”或“卖出”按钮进行委托。可出现一个委托提示框提示是否继续委托操…