QPieSeries QPieSlice label 标签重叠解决方案

demo 下载地址在最后


通常我们在用QPieSeries 做饼状图,并且饼状图几个部分差别不太大时,label 标签展示都是正常的,期望如下图:

一般情况下做这种饼状图很简单,如:

    QPieSeries *series = new QPieSeries(this);
    series->append("迟到人数22", 22);
    series->append("旷工人数35", 35);
    series->append("正常出勤人数97", 97);
    series->setLabelsVisible();

    QPieSlice *slice1 = series->slices().at(0);
    QPieSlice *slice2 = series->slices().at(1);
    QPieSlice *slice3 = series->slices().at(2);
    slice1->setColor(QColor(79, 129, 189));
    slice2->setColor(QColor(192, 80, 77));
    slice3->setColor(QColor(155, 187, 89));

    QChart *chart = new QChart();
    chart->addSeries(series);
    chart->setTitle("PieChart");
    chart->legend()->hide();

    QChartView *chartview = new QChartView(chart);
    chartview->setRenderHint(QPainter::Antialiasing);
    ui->widget->layout()->addWidget(chartview);

 我们展示了三个标签,数据分别是22, 35 和 97,label 展示的也都正常。但是有一种情况,就是当其中两个数据很小时,会出现标签label 重叠的问题,例如我们将pie的三组数据分别更改为 1, 2 和 97时,就会label就会重叠:

 这显然不是我们想要的。但是怎么样才能避免这种标签重叠的现象呢?其实原理很简单,出现这种情况的原因有两个:

1. 相邻的两个slice 块数值(比例)都很小;

2. 这两个slice 块都在起始角度的一侧;

第二点就是我们要解决这种情况的切入点。 

因为添加  slice 的顺序就是从起始角度开始展示的顺序,例如上面错误的图我们添加的顺序就是小,小,大的顺序,也就是从起始角度(12点钟方向开始顺时针添加),结果就会造成上面的现象。

    QPieSeries *series = new QPieSeries(this);
    series->append("迟到人数1", 1);
    series->append("旷工人数2", 2);
    series->append("正常出勤人数97", 97);

那么我们添加两个最小的 slice 分别显示在起始角度的两侧,那么添加顺序就应该是 小、大、小了,也就是优化一下添加顺序, 就能得出让我们满意的结果。

    series->append("迟到人数1", 1);
    series->append("正常出勤人数97", 97);
    series->append("旷工人数2", 2);

两个新的问题:

1.  局限性:slice的个数不是固定的且每个slice 的大小是会变化的,我们不能写死数据。

2.  每个 slice 颜色是不固定的,最小的永远都是蓝色,最大的永远都是红色...

解决方案:

 我们要解决上面的问题,就要写成一个通用的控件,如果有n个slice,我们就需要对每个slice 按照 数值大小进行排成 : “小-大-小-大...” 的顺序。

如果对每个slice有固定颜色的需求(例如,出勤人数使用绿色,缺勤人数使用红色),我们需要将颜色与slice 进行绑定,没有此需求的可以略过。为做成通用类型,我们slice 绑定固定的颜色。

所以,我们需要将每个slice 信息封装成一个结构体 SliceInfo:

struct SliceInfo{
    int     m_value;        // 数值
    QString m_labelName;    // label 标签
    QColor  m_color;        // 颜色

    SliceInfo(int value, QString name, QColor color) {
        m_value = value;
        m_labelName = name;
        m_color = color;
    }
};

所以,对于n个slice ,我们需要封装一个方法,能够根据 n个SliceInfo 创建排好序的 n个 QPieSlice 对象。然后我们只需要将获取的QPieslice 对象依次添加到 QPieSeries 中即可:

QList<QPieSlice*> MainWindow::sortPie(QList<SliceInfo> &slicesInfo)
{
    // 1. 排序 value "小大小大"  的顺序排列
    QList<SliceInfo> sortSliceInfo;
    bool bMin  = true;
    int count = slicesInfo.size();
    for (int i = 0; i < count; i++) {
        int index = 0;
        for (int j = 1; j < slicesInfo.size(); j++) {
            if (bMin) { // 取最小数
                if (slicesInfo.at(index).m_value > slicesInfo.at(j).m_value) {
                    index = j;
                }
            } else { // 取最大数
                if (slicesInfo.at(index).m_value < slicesInfo.at(j).m_value) {
                    index = j;
                }
            }
        }

        SliceInfo info = slicesInfo.takeAt(index);
        sortSliceInfo.append(info);

        // 交替取大小数
        bMin = !bMin;
    }

    // 2. 创建
    QList<QPieSlice*> slices;
    for (int i = 0; i < sortSliceInfo.size(); i++) {
        QPieSlice *pieSlice = new QPieSlice(sortSliceInfo.at(i).m_labelName, sortSliceInfo.at(i).m_value);
        pieSlice->setColor(sortSliceInfo.at(i).m_color);
        slices.append(pieSlice);
    }

    return slices;
}

这样,我们就可以在获取信息后进行创建一系列排好序的slice了

    QList<SliceInfo> piesInfo;
    piesInfo.append(SliceInfo(1, "迟到人数1", QColor(79, 129, 189)));
    piesInfo.append(SliceInfo(2, "旷工人数2", QColor(192, 80, 77)));
    piesInfo.append(SliceInfo(97, "正常出勤人数97", QColor(155, 187, 89)));

    // 排序
    QList<QPieSlice*> pies = sortPie(piesInfo);

    QPieSeries *series = new QPieSeries(this);
    for (int i = 0; i < pies.size(); i++) {
        series->append(pies.at(i));
    }

 这样我们就用一个通用的方法来解决了QPieSeries QPieSlice label 标签重叠的问题。

demo 免费下载地址 :QT_QPieSeries_QPieSlicelabel标签重叠解决方案-QT文档类资源-CSDN下载QtQPieSeriesQPieSlicelabel标签重叠解决方案详细介绍请参见博客:更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/xiezhongyuan07/85227152

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值