Qt自定义控件6:自定义饼状图
先看效果图:
思路:在类中定义一个Part用来存储每一个图中部分的属性,包含 占比,颜色,part的文字。使用qlist存储多个part,给外界提供addPart(。。。)方法,画图时直接根据占比得到角度画圆弧。
效果图是在调用时添加了4个分别占25%的part。
关键代码:CMPerChart1.cpp
void CMPerChart1::paintEvent(QPaintEvent *event){
int width = this->width();
int height = this->height();
int side = qMin(width, height);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0);
drawFrame(&painter);
drawChartName(&painter); //画图的名称
if(ltPart.count()>0){
drawPart(&painter);
drawPartText(&painter);//在每个部分中画上文字
}
}
void CMPerChart1::drawFrame(QPainter *painter){
painter->setPen(Qt::NoPen);
//画外圈边缘及外圈
int outSideRadius = outRadius+outSide;
painter->save();
painter->setBrush(QBrush(QColor("#E4E4E4")));
painter->drawEllipse(-outSideRadius,-outSideRadius,2*outSideRadius,2*outSideRadius);
painter->restore();
painter->save();
painter->setBrush(QBrush(QColor("#FFFFFF")));
painter->drawEllipse(-outRadius,-outRadius,2*outRadius,2*outRadius);
painter->restore();
//画内圈边缘及内圈
int inSideRadius = inSide+inRadius;
painter->save();
painter->setBrush(QBrush(QColor("#E4E4E4")));
painter->drawEllipse(-inSideRadius,-inSideRadius,2*inSideRadius,2*inSideRadius);
painter->restore();
painter->save();
painter->setBrush(QBrush(QColor("#FFFFFF")));
painter->drawEllipse(-inRadius,-inRadius,2*inRadius,2*inRadius);
painter->restore();
}
void CMPerChart1::drawChartName(QPainter *painter){
int textRadius = inRadius-textSide;
painter->save();
painter->setPen(QPen(Qt::black));
QFont font = painter->font();
font.setPixelSize(8);
painter->setFont(font);
QRectF rect(-textRadius,-textRadius,2*textRadius,2*textRadius);
painter->drawText(rect,Qt::AlignCenter,chartname);
painter->restore();
}
void CMPerChart1::drawPart(QPainter *painter){
for(Part part : ltPart){
int out = outRadius;
int in = inRadius+inSide;
int adjust = out-in;
//画part圆弧
painter->save();
painter->setBrush(part.partColor);
QRectF rect(-out, -out, out << 1, out << 1);
QPainterPath path;
path.arcTo(rect, part.partRStart, part.partPercent*360);
QPainterPath subPath;
subPath.addEllipse(rect.adjusted(adjust, adjust, -adjust, -adjust));
path -= subPath;
painter->setPen(Qt::NoPen);
painter->drawPath(path);
painter->restore();
// //画part的text
// painter->save();
// painter->setPen(Qt::black);
// int textRaidus = (out+in)/2;
// float textRange =(part.partRStart+part.partREnd)/2;
// float x = textRaidus*qCos(textRange);
// float y = textRaidus*qSin(textRange);
// qDebug()<<textRange<<","<<x<<","<<y;
// painter->drawText(x-12,y,part.partname);
// painter->restore();
}
}
void CMPerChart1::drawPartText(QPainter *painter){
int out = outRadius;
int in = inRadius+inSide;
for(Part part : ltPart){
//画part的text
painter->save();
painter->setPen(Qt::black);
int textRaidus = (out+in)/2;
float textRange =(part.partRStart+part.partREnd)/2;
float x = textRaidus*qCos(textRange/180*3.14);
float y = -textRaidus*qSin(textRange/180*3.14);
qDebug()<<textRange<<","<<x<<","<<y;
painter->drawText(x-15,y,part.partname);
painter->restore();
}
}
void CMPerChart1::drawPartSpacer(QPainter *painter){
}
void CMPerChart1::addPart(QString partname,QColor partColor,float partPercent){
Part newPart;
newPart.partname = partname;
newPart.partColor = partColor;
newPart.partPercent = partPercent;
int count = ltPart.count();
if(count>0){
newPart.partRStart = ltPart.at(count-1).partREnd;
}else{
newPart.partRStart =0;
}
float range = partPercent*360;
newPart.partREnd = newPart.partRStart+range;
if(newPart.partREnd>360){
qDebug()<<"range>360,the percent is wrong";
}
ltPart.append(newPart);
update();
}