Qt自定义饼图(重叠、切片、圆环、高亮)

由于项目中遇到饼图各个切片重合的情况,虽然可以通过设置透明度进行颜色融合,但仍然不能满足需求,思考再三,想出普通饼图+环形外框的方案,大家一起来看看效果吧!

 

关键代码如下:

void PiePanel::initViewData(QPainter *painter)
{
    int border_width = 1;
    QString label_str = partitionPieInfo_.name;
    QFont font = painter->font();
    font.setPixelSize(TITLE_PIXEL_SIZE);
//    font.setBold(true);
    QFontMetrics fm(font);
    int pixelsWide = fm.width(label_str);
    int pixelsHigh = fm.height();
    //! draw header
    painter->save();
    QPen pen(Qt::black, border_width);
    pen.setStyle(Qt::DashLine);
    painter->setFont(font);
    painter->setPen(pen);
    painter->drawText(QPoint(2, pixelsHigh), label_str); // (this->width()-pixelsWide)/2
    painter->restore();

    //!重叠
    QMap<QString, QPair<int, int> > overlayMap; // 名称, offset; 宽度

    painter->save();
    painter->setRenderHints(QPainter::Antialiasing);
    QMap<double,QString> degreeMap;
    int offset_ = 1;
    all_labels_map_.clear();
    for(auto partitionInfo:partitionPieInfo_.partitionInfoContainer)
    {
        double startDegree = -(partitionInfo.startTime/partitionPieInfo_.allTime*360)+90;//开始角度
        double endDegree = startDegree-(partitionInfo.durationTime/partitionPieInfo_.allTime*360);//结束角度

        //获取周期单位下的开始时间
        TimeValue startTime(partitionInfo.startTime,TimeUnit::Nanosecond);
        double startTimeValue = startTime.getValueWithUnit(partitionPieInfo_.unit);
        QString startTimeStr = QString::number(startTimeValue) + UNIT_STR_MAP.value(partitionPieInfo_.unit);

        //获取周期单位下的结束时间
        TimeValue endTime(partitionInfo.startTime+partitionInfo.durationTime,TimeUnit::Nanosecond);
        double endTimeValue = endTime.getValueWithUnit(partitionPieInfo_.unit);
        QString endTimeStr = QString::number(endTimeValue) + UNIT_STR_MAP.value(partitionPieInfo_.unit);

        //记录所有开始和结束数据
        degreeMap.insert(startDegree,startTimeStr);
        degreeMap.insert(endDegree,endTimeStr);

        int partitionstartAngle = startDegree;
        int partitionspanAngle = -(partitionInfo.durationTime/partitionPieInfo_.allTime*360);

        //配置分区信息
        PieFrameInfo pieFrameInfo;
        pieFrameInfo.name = partitionInfo.name;
        pieFrameInfo.startTime = startTimeStr;
        pieFrameInfo.endTime = endTimeStr;

        outCount = partitionInfo.taskInfoContainer.count();
        for(auto task:partitionInfo.taskInfoContainer)
        {
            //获取周期单位下的开始时间
            TimeValue taskStartTime(task.startTime,TimeUnit::Nanosecond);
            double taskStartTimeValue = taskStartTime.getValueWithUnit(partitionPieInfo_.unit);
            QString taskStartTimeStr = QString::number(taskStartTimeValue) + UNIT_STR_MAP.value(partitionPieInfo_.unit);

            //获取周期单位下的结束时间
            TimeValue taskEndTime(task.startTime+task.durationTime,TimeUnit::Nanosecond);
            double taskEndTimeValue = taskEndTime.getValueWithUnit(partitionPieInfo_.unit);
            QString taskEndTimeStr = QString::number(taskEndTimeValue) + UNIT_STR_MAP.value(partitionPieInfo_.unit);

            //配置任务信息
            PieInfo pieInfo;
            pieInfo.name = task.name;
            pieInfo.startTime = taskStartTimeStr;
            pieInfo.endTime = taskEndTimeStr;

            //角度
            int startAngle = -(task.startTime/partitionPieInfo_.allTime*360)+90;//开始角度
            int spanAngle = -(task.durationTime/partitionPieInfo_.allTime*360);//跨越角度

            //设置alpha
            QColor tmpColor = task.pieColor;
            tmpColor.setAlpha(100);
            QString childLabelStr = tr("%1(%2~%3)").arg(pieInfo.name).arg(pieInfo.startTime).arg(pieInfo.endTime);

            QFont font = painter->font();
            font.setPixelSize(10);
            QFontMetrics fm(font);
            int font_width = fm.width(childLabelStr)+5;
            QString tmpKey = tr("%1,%2").arg(startAngle).arg(spanAngle);
            if(overlayMap.contains(tmpKey))
            {
                overlayMap[tmpKey] = qMakePair(overlayMap[tmpKey].first + 1, overlayMap[tmpKey].second + font_width);
            }
            else
            {
                overlayMap[tmpKey] = qMakePair(1, font_width);
            }
            drawPie(painter, startAngle*16, spanAngle*16, tmpColor, childLabelStr, offset_ ++,  overlayMap[tmpKey]);
        }

        drawBorder(painter,partitionstartAngle*16,partitionspanAngle*16);
    }

    //! 分区外框虚线的起始时间&结束时间
    QMap<double, int> ready_draw_map;//whp add 2021-11-10,两个文本如果y值重合,那么就进行上移操作。
    QList<double> keyList = degreeMap.keys();//获取需要绘制文本的角度
    for(auto degree:keyList){
        QString text = degreeMap.value(degree);

        QFontMetrics fm(this->font());
        int pixelsWide = fm.width(text);
        int pixelsHigh = fm.height();

        float radians = qDegreesToRadians(degree);
        int x_center = this->width() / 2;
        int y_center = this->height() * CENTER_OFFSET_PERCENT;
        int x = (radius_ + BORDER_TEXT_OFFSET)*(qCos(radians));
        int y = (radius_ + BORDER_TEXT_OFFSET)*(-qSin(radians));

        textTransformation(x,y,pixelsWide,pixelsHigh);

        if(ready_draw_map.contains(y))
        {
            int value = ready_draw_map[y];
            ready_draw_map[y] = value + 1;
            y = y + value * 10;
        }
        else
        {
            ready_draw_map.insert(y, 1);
        }

        x = x + x_center;
        y = y + y_center - pixelsHigh;

        QFont font = painter->font();
        font.setPixelSize(SCALE_PIXEL_SIZE);
        painter->setFont(font);
        painter->drawText(QRect(x,y,pixelsWide,pixelsHigh),text);
    }

    painter->restore();
}

 全套代码链接:🍞正在为您运送作品详情

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值