#include "RadarCtrl.h"
#include <QPainter>
#include <math.h>
RadarCtrl::RadarCtrl(QWidget *parent,int h) :
QWidget(parent)
{
setFixedSize(h+100,h);
m_type = e_polygon;
m_colorCircle = Qt::gray;
m_nCount = 0;
}
RadarCtrl::~RadarCtrl()
{
QMap<QString,QCheckBox*>::Iterator it = m_mapCheckbox.begin();
for(;it!=m_mapCheckbox.end();it++)
{
delete it.value();
}
m_mapCheckbox.clear();
}
//设置雷达图的显示方式
void RadarCtrl::setShowType(ERadarPicType e)
{
m_type = e;
}
//设置雷达图的要素
void RadarCtrl::setElementName(QStringList ele)
{
m_listEle = ele;
}
//设置雷达图要素的最大值
void RadarCtrl::setMaxVaue(QList<int> val)
{
m_listMaxVal.clear();
m_listMaxVal = val;
}
//添加数据
void RadarCtrl::addData(QString name, QList<double> data)
{
m_nCount++;
QColor cc = getColor();
QCheckBox* box = new QCheckBox(this);
box->setFixedWidth(100);
box->setText(name);
box->setChecked(true);
//设置checkbox背景色
QPalette pe ;
pe.setBrush(QPalette::WindowText,cc);
box->setPalette(pe);
connect(box,SIGNAL(clicked()),this,SLOT(slotCheckBoxClicked()));
//添加前缀,为了保证先加入的先画,不会因为QMAP的自动排序打乱顺序
name = QString("%1").arg(m_nCount,3,10,QLatin1Char('0')) + name;
m_mapdata.insert(name,data);
m_mapcolor.insert(name,cc);
//添加到map中
m_mapCheckbox.insert(name,box);
//调整checkbox的位置
int het = 30;
int top = (this->height() - m_mapCheckbox.size() * het)/2;
QMap<QString,QCheckBox*>::Iterator it = m_mapCheckbox.begin();
for(int i = 0;it!=m_mapCheckbox.end();it++,i++)
{
QCheckBox* box = it.value();
box->move(this->width() - 100,top + i * het);
}
}
//设置圆环填充色
void RadarCtrl::setCircleColor(QColor c)
{
m_colorCircle = c;
}
//绘制
void RadarCtrl::paintEvent(QPaintEvent *)
{
int nradius = (this->height() - 100)/2; //这里的100,需要根据字符串像素大小调整,使得能够放下雷达顶点的要素名称
int nstep = nradius/5;
nradius = 5*nstep; //确保5等分
double thta = 360.0/m_listEle.size();
//计算雷达图中心点的位置
int centx = this->height() /2;
int centy = centx;
QPainter painter(this);
painter.save();
painter.setRenderHint(QPainter::Antialiasing); //设置反锯齿
//计算顶点的位置
QList<QPointF> ls1,ls2,ls3,ls4,ls5; //保存雷达图每层的顶点
ls1 = caculateVertex(centx,centy,nradius,thta,m_listEle.size());
ls2 = caculateVertex(centx,centy,nradius-nstep,thta,m_listEle.size());
ls3 = caculateVertex(centx,centy,nradius-2*nstep,thta,m_listEle.size());
ls4 = caculateVertex(centx,centy,nradius-3*nstep,thta,m_listEle.size());
ls5 = caculateVertex(centx,centy,nradius-4*nstep,thta,m_listEle.size());
QPainterPath p1,p2,p3,p4,p5; //保存5层标准路径
//绘制圆环
if(m_type == e_circle) //圆形
{
p1 = createCirclePath(centx,centy,nradius);
p2 = createCirclePath(centx,centy,nradius - nstep);
p3 = createCirclePath(centx,centy,nradius - 2*nstep);
p4 = createCirclePath(centx,centy,nradius - 3*nstep);
p5 = createCirclePath(centx,centy,nradius - 4*nstep);
}else
{
p1 = createPolygonPath(ls1);
p2 = createPolygonPath(ls2);
p3 = createPolygonPath(ls3);
p4 = createPolygonPath(ls4);
p5 = createPolygonPath(ls5);
}
painter.drawPath(p1-p2);
painter.setBrush(m_colorCircle);
painter.drawPath(p2-p3);
painter.setBrush(Qt::NoBrush);
painter.drawPath(p3-p4);
painter.setBrush(m_colorCircle);
painter.drawPath(p4-p5);
painter.setBrush(Qt::NoBrush);
if(m_type == e_circle)
painter.drawEllipse(QPointF(centx,centy),nradius - 4*nstep,nradius - 4*nstep);
else
painter.drawPath(p5);
QFont font = painter.font(); //获取当前的字体(或者设置需要的字体)
//font.setFamily(QString::fromUtf8("微软雅黑"));
//font.setPointSize(12);
//painter.setFont(font);
//绘制基准线和文本
for(int i = 0; i< ls1.size(); i++)
{
//基准线
painter.setPen(Qt::black);
painter.drawLine(QPointF(centx,centy),ls1.at(i));
//计算文本的宽度、高度,及所在的位置(宽度如果过长,考虑分行显示,也可以直接使用QLabel来容纳文本,然后调整QLabel的位置即可)
QRect rc = getStringRect(m_listEle.at(i),font); //字符串的宽度与高度与字体有关
int xx,yy;
if(ls1.at(i).x() == centx)
xx = centx - rc.width()/2;
else if(ls1.at(i).x() > centx)
xx = ls1.at(i).x() + 5;
else
xx = ls1.at(i).x() - rc.width() - 5;
if(i == 0)
yy = ls1.at(0).y() - 5;
else
{
if(ls1.at(i).y() < centy)
yy = ls1.at(i).y() + rc.height()/2 - 3;
else
yy = ls1.at(i).y() + rc.height()/2 + 3;
}
//绘制文本
painter.drawText(xx,yy,m_listEle.at(i)); //yy是文本矩形的底部
}
//绘制数据
QMap<QString,QList<double> >::Iterator it = m_mapdata.begin();
painter.setPen(Qt::NoPen);
for(; it != m_mapdata.end();it++)
{
QCheckBox* box = m_mapCheckbox.find(it.key()).value();
if(box->isChecked())
{
painter.setBrush(m_mapcolor.find(it.key()).value());
QPainterPath pt = createDataPath(centx,centy,nradius,it.value(),ls1);
painter.drawPath(pt);
}
}
painter.restore();
}
//计算顶点的位置
QList<QPointF> RadarCtrl::caculateVertex(int centx,int centy,int radius, double thta, int nmb)
{
QList<QPointF> points;
for(int i = 0;i<nmb; i++)
{
double ang = thta * i / 180.0 * M_PI;
int x,y;
if(ang <= M_PI/2)
{
x = sin(ang) * radius;
y = cos(ang) * radius;
x = centx + x;
y = centy - y;
}else if( ang > M_PI/2 && ang <= M_PI)
{
x = cos(ang - M_PI/2) * radius;
y = sin(ang - M_PI/2) * radius;
x = centx + x;
y = centy + y;
}else if( ang > M_PI && ang <= 1.5*M_PI )
{
x = sin(ang - M_PI) * radius;
y = cos(ang - M_PI) * radius;
x = centx - x;
y = centy + y;
}else
{
x = sin(2*M_PI - ang) * radius;
y = cos(2*M_PI - ang) * radius;
x = centx - x;
y = centy - y;
}
points.push_back(QPointF(x,y));
}
return points;
}
//创建圆环路径
QPainterPath RadarCtrl::createCirclePath(int centx, int centy, int nradius)
{
QPainterPath path;
path.moveTo(centx,centy);
path.arcTo(QRect((height()-nradius*2)/2,(height()-nradius*2)/2,nradius*2,nradius*2) ,0,360);
return path;
}
//创建多边形路径
QPainterPath RadarCtrl::createPolygonPath(QList<QPointF> points)
{
QPainterPath path;
path.moveTo(points.at(0));
for(int i = 1; i< points.size(); i++)
path.lineTo(points.at(i));
path.lineTo(points.at(0));
return path;
}
//获取字符串所占的像素宽度和高度
QRect RadarCtrl::getStringRect(QString str,QFont font)
{
QFontMetrics fm(font);
QRect rect = fm.boundingRect(str);
return rect;
}
//获取随机颜色
QColor RadarCtrl::getColor()
{
int r = 0;
int g = 0;
int b = 0;
r += 22;g+= 34;b+=66;
r = rand() % 256;
g = rand() % 256;
b = rand() % 256;
return QColor(r,g,b,200);
}
//获取数据路径T
- 1
- 2
- 3
前往页