QtChart实现极坐标图(雷达图)——QtWidgets

1. 前言

突然好奇极坐标图(雷达图)是怎么实现的,就查了一下资料,发现有几种实现方法:一是QtChart实现;二是QCustomPlot实现;三是自绘。前两者都给了示例,所以我就学了学,后者自绘我尽力吧。

2. 说明和代码

QtChart实现图表一般要设置三部分:模型、数据、轴,如果要实现极坐标图,三者分别为:

  • 模型:必须为QPolarChart;
  • 数据:想要什么样的数据表达形式,可选择不同的类来存储数据,比如散点选择QScatterSeries、直线选择QLineSeries等;
  • :轴也是根据表现形式的不同选择不同的轴类,都是继承QAbstractAxis,最常用到的是QValueAxis。

2.1. 一般结构代码

这里先给个示例代码:

    const qreal angularMin = -100;
    const qreal angularMax = 100;

    const qreal radialMin = -100;
    const qreal radialMax = 100;

    //数据
    QScatterSeries *series1 = new QScatterSeries();
    series1->setName("scatter");
    for (int i = angularMin; i <= angularMax; i += 10)
        series1->append(i, (i / radialMax) * radialMax + 8.0);

    //模型
    QPolarChart *chart = new QPolarChart();
    chart->addSeries(series1);

    //轴
    QValueAxis *angularAxis = new QValueAxis();
    angularAxis->setTickCount(9); // First and last ticks are co-located on 0/360 angle.
    angularAxis->setLabelFormat("%.1f");
    angularAxis->setShadesVisible(true);
    angularAxis->setShadesBrush(QBrush(QColor(249, 249, 255)));
    chart->addAxis(angularAxis, QPolarChart::PolarOrientationAngular);

    QValueAxis *radialAxis = new QValueAxis();
    radialAxis->setTickCount(9);
    radialAxis->setLabelFormat("%d");
    chart->addAxis(radialAxis, QPolarChart::PolarOrientationRadial);

    series1->attachAxis(radialAxis);
    series1->attachAxis(angularAxis);

    radialAxis->setRange(radialMin, radialMax);
    angularAxis->setRange(angularMin, angularMax);

    //最后加载到视图上
    ChartView *chartView = new ChartView();
    chartView->setChart(chart);
    chartView->setRenderHint(QPainter::Antialiasing);

结构大概就是上面的那个结构,一般变化的就是数据表现形式:可以是线性QLineSeries、散点QScatterSeries,区域QAreaSeries等,或者两两结合的,比如线性跟区域的结合等;或者散点中的点的形状大小的变化。

2.2.  线面结合(区域填充)

线性QLineSeries跟区域QAreaSeries的结合,就是在一个区域内进行一个填充。区域是由QAreaSeries设置上方线条(setUpperSeries)和下方线条(setLowerSeries)构成的,可不设置下方线条,线条也可不闭环。代码如下:

    QLineSeries* series = new QLineSeries();     // 创建一个散点绘图数据集对象
    series->setPen(QPen(QColor(Qt::blue)));

       for(int i=0;i<100;i++){
        series->append(i/100.0*360.0,qSin(i/100.0*M_PI*6)*2);
    }
    QAreaSeries *series4 = new QAreaSeries();
    series4->setUpperSeries(series);
    series4->setPen(QPen(QColor(255,150,20,0)));
    series4->setBrush(QColor(255,150,20,50));


    ....

    chart->addSeries(series);                         
    chart->addSeries(series4);
    
    ...

    series->attachAxis(angularAxis);
    series->attachAxis(radialAxis);
    series4->attachAxis(angularAxis);
    series4->attachAxis(radialAxis);
    ....

效果图如下:

2.3. QScatterSeries的点

这里着重说一下散点类QScatterSeries,它的点可改变大小和形状,大概有以下几种方式。

2.3.1. 只设置Mask形状和大小

散点类QScatterSeries可设置Marker的形状和大小,形状默认为圆(QScatterSeries::MarkerShapeCircle),这里设置的是长方形,它只有这两个形状,代码如下:

    QScatterSeries *series2 = new QScatterSeries();
    series2->setMarkerShape(QScatterSeries::MarkerShapeRectangle);
    qreal markSize=7.0;
    series2->setMarkerSize(markSize);

2.3.2.  加载图片填充点

QScatterSeries 可通过设置刷子来改变点Marker内的填充,可以看QBrush的构造函数,可用QImage进行初始化,所以我们可以直接加载图片作为点内部的填充,其中,要搭配Marker来控制点的大小和形状。

    QImage star(":/res/ssStar.png");
    star=star.scaled(markSize,markSize);
    series2->setBrush(star);
    series2->setPen(QColor(Qt::transparent));

2.3.3. QPainter绘制图案填充点 

既然可以用QImage进行填充点,那么就可以用painter进行绘制。

QImage star(markSize, markSize, QImage::Format_ARGB32);
star.fill(Qt::transparent);

QPainter painter(&star);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QPen(Qt::blue));
painter.drawLine(QLineF(0,markSize/2.0, markSize,markSize/2.0));
painter.drawLine(QLineF(markSize/2.0, markSize,   markSize, 0));
painter.drawLine(QLineF(0.15*markSize,0.15*markSize, 0.85*markSize,0.85*markSize));
painter.drawLine(QLineF(0.15*markSize, 0.85*markSize, 0.85*markSize, 0.15*markSize));
series2->setBrush(star);
series2->setPen(QColor(Qt::transparent));

效果图如下:

 散点若与线条同路径,与上面的线面结合的在同一个坐标下,图如下,

3. 结束语

最近学了下QCustomPlot,发现QCustomPlot更简单,性能更好,而且只需要有两个线条就可以完成上图,下篇博客就写这个。综上所述,这个只是个示例,若用在项目中,还是准备用QCustomPlot。

猜你喜欢

转载自blog.csdn.net/xiaopei_yan/article/details/129854093
今日推荐