qcustomplot绘制柱状图

本文详细介绍了如何在Qt项目中集成QCustomPlot库,创建自定义柱状图,并展示了如何设置颜色、间距、数据绘制和文本显示。通过实例代码,读者可以学习如何扩展QCustomPlot的功能并应用于实际项目中。
摘要由CSDN通过智能技术生成

一、创建项目工程

1、创建qt 工程
2、将下载的QCustomPlot源文件的.c .h文件分别添加到源文件和头文件中
3、在./pro中添加
QT += widgets printsupport
4、在Ui界面中添加一个新的widget控件
右击鼠标选择“提升为”,提升类名称输入“QCustomPlot”,点击添加,点击提升
如图所示
在这里插入图片描述

二、主要代码

1、.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QVector>
#include <QString>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    //绘制柱状图对象
    minBar = new CustomBars (ui->qcustomplot->xAxis,ui->qcustomplot->yAxis);
    maxBar = new CustomBars (ui->qcustomplot->xAxis,ui->qcustomplot->yAxis);
    fossil = new CustomBars (ui->qcustomplot->xAxis,ui->qcustomplot->yAxis);
    initBar();
}
void Widget::initBar()
{
    //设置画笔颜色red, green,blue,
    minBar->setPen(QPen(Qt::red));
    maxBar->setPen(QPen(Qt::green));
    fossil->setPen(QPen(Qt::blue));
    //设置填充颜色

    minBar->setBrush(Qt::red);
    maxBar->setBrush(Qt::green);
    fossil->setBrush(Qt::blue);

    QCPBarsGroup *group = new QCPBarsGroup(ui->qcustomplot);
    group->setSpacingType(QCPBarsGroup::stAbsolute);  // 设置组内柱状图的间距,按像素
    group->setSpacing(0);     // 设置较小的间距值,这样看起来更紧凑

    fossil->setBarsGroup(group);
    maxBar->setBarsGroup(group);
    minBar->setBarsGroup(group);
    //设置大小
    //minBar->setBaseValue(0.5); //设置柱状图距离x轴的距离
    //设置柱状图的宽度
    minBar->setWidth(0.5);
    maxBar->setWidth(0.5);
    fossil->setWidth(0.5);

    //设置抗锯齿
    minBar->setAntialiased(false); // gives more crisp, pixel aligned bar borders
    maxBar->setAntialiased(false);
    fossil->setAntialiased(false);
    addValue();
}
void Widget::addValue()
{
    //设置坐标
    QVector<double> ticks;
    QVector<QString> labels;
    //添加元素,将拉大刻度间的间距
    int count = 2;
    for(int i =1 ;i <20;i++)
    {
        if(i == count)
        {
             ticks <<i;
             count +=2;

        }

    }
    count = 0;
    for(int i =2 ;i <30;i++)
    {
        if(i == 2+count)
        {
            labels << QString::number(i,10);
            count +=1;
        }

    }
    //共享指针--坐标轴的设置
    QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
    textTicker->addTicks(ticks, labels);

    ui->qcustomplot->plotLayout()->insertRow(0);
    //添加x轴
    ui->qcustomplot->xAxis->setTicker(textTicker);
    //设置标签的旋转
    ui->qcustomplot->xAxis->setTickLabelRotation(0);
    ui->qcustomplot->xAxis->setSubTicks(false);
    //设置刻度线的长度
    ui->qcustomplot->xAxis->setTickLength(0, 4);
    //设置x轴的范围
    ui->qcustomplot->xAxis->setRange(0,20);

    //分层设置
    ui->qcustomplot->xAxis->grid()->setVisible(false);
    ui->qcustomplot->yAxis->grid()->setSubGridVisible(false);
    ui->qcustomplot->yAxis->setSubTicks(false);
    //设置y轴的范围
    ui->qcustomplot->yAxis->setRange(0,15);

    QVector<double> y,y1,y2;
    y << 9 << 7 << 5 << 2 << 7 << 4 << 9 << 1;
    y1 << 1 << 9.03 << 6 << 2 << 7 << 3<< 1 << 9;
    y2 << 9.87 << 7 << 5 << 2 << 7.12 << 4 << 9 << 1;

    minBar->addData(ticks,y);
    maxBar->addData(ticks,y1);
    fossil->addData(ticks,y2);
    //刷新曲线
    ui->qcustomplot->replot();
}

Widget::~Widget()
{
    delete ui;
}

2、custombars.cpp文件

#include "custombars.h"

CustomBars::CustomBars(QCPAxis *keyAxis, QCPAxis *valueAxis)
    : QCPBars(keyAxis, valueAxis),
      mTextAlignment(Qt::AlignCenter),
      mSpacing(5),
      mFont(QFont(QLatin1String("sans serif"), 12))
{

}

void CustomBars::setTextAlignment(Qt::Alignment alignment)
{
    mTextAlignment = alignment;
}

void CustomBars::setSpacing(double spacing)
{
    mSpacing = spacing;
}

void CustomBars::setFont(const QFont &font)
{
    mFont = font;
}

void CustomBars::draw(QCPPainter *painter)
{
    if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
    if (mDataContainer->isEmpty()) return;
    //定义两个图表数据容器
    QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd;
    //获取可见数据范围
    getVisibleDataBounds(visibleBegin, visibleEnd);

    // loop over and draw segments of unselected/selected data:
    QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
    getDataSegments(selectedSegments, unselectedSegments);
    allSegments << unselectedSegments << selectedSegments;
    for (int i = 0; i < allSegments.size(); ++i)
    {
        bool isSelectedSegment = i >= unselectedSegments.size();
        QCPBarsDataContainer::const_iterator begin = visibleBegin;
        QCPBarsDataContainer::const_iterator end = visibleEnd;
        mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
        if (begin == end)
            continue;

        for (QCPBarsDataContainer::const_iterator it = begin; it != end; ++it)
        {
            // draw bar:
            if (isSelectedSegment && mSelectionDecorator)
            {
                mSelectionDecorator->applyBrush(painter);
                mSelectionDecorator->applyPen(painter);
            }
            else
            {
                painter->setBrush(mBrush);
                painter->setPen(mPen);
            }
            applyDefaultAntialiasingHint(painter);
            QRectF barRect = getBarRect(it->key, it->value);   //自己加的  绘制矩形
            float ww = barRect.width();
            //这两个设置可以修改柱状图与Y轴的距离
           // barRect.setLeft(barRect.left()+ww-20);  //设置矩形的左边缘
           // barRect.setRight(barRect.right()+ww-20);//设置矩形的右边缘
            barRect.setLeft(barRect.left()+ww); 
            barRect.setRight(barRect.right()+ww);
            //绘制多边形
            painter->drawPolygon(barRect);
            // 以上是拷贝的源码部分
            painter->drawPolygon(barRect);

            // 我们仅需在 painter->drawPolygon(barRect); 这行下增加以下的内容即可

            // 计算文字的位置
          //  mFont.setPointSize(6);
            painter->setFont(mFont);                     // 设置字体
            QString text  = QString::number(it->value, 'g', 2);   // 取得当前value轴的值,保留两位精度

            QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip | mTextAlignment, text);  // 计算文字所占用的大小

            if (mKeyAxis.data()->orientation() == Qt::Horizontal) {    // 当key轴为水平轴的时候
                if (mKeyAxis.data()->axisType() == QCPAxis::atTop)     // 上轴,移动文字到柱状图下面
                    textRect.moveTopLeft(barRect.bottomLeft() + QPointF(0, mSpacing));
                else                                                   // 下轴,移动文字到柱状图上面
                    textRect.moveBottomLeft(barRect.topLeft() - QPointF(0, mSpacing));
                textRect.setWidth(barRect.width());
                painter->drawText(textRect, Qt::TextDontClip | mTextAlignment, text);
            }
            else {                                                  // 当key轴为竖直轴的时候
                if (mKeyAxis.data()->axisType() == QCPAxis::atLeft)   // 左轴,移动文字到柱状图右边
                    textRect.moveTopLeft(barRect.topRight() + QPointF(mSpacing, 0));
                else                                                  // 右轴,移动文字到柱状图左边
                    textRect.moveTopRight(barRect.topLeft() - QPointF(mSpacing, 0));
                textRect.setHeight(barRect.height());
                painter->drawText(textRect, Qt::TextDontClip | mTextAlignment, text);
            }

        }
    }

}

3、.h文件

custombars.h

#ifndef CUSTOMBARS_H
#define CUSTOMBARS_H

#include "qcustomplot.h"

class CustomBars : public QCPBars
{
    Q_OBJECT

public:
    explicit CustomBars(QCPAxis *keyAxis, QCPAxis *valueAxis);

    Qt::Alignment textAligment() const { return mTextAlignment; }
    double spacing() const { return mSpacing; }
    QFont font() const { return mFont; }

    void setTextAlignment(Qt::Alignment alignment);
    void setSpacing(double spacing);
    void setFont(const QFont &font);
protected:
    Qt::Alignment mTextAlignment;   // 文字对齐方式
    double mSpacing;                // 文字与柱状图的间距,这里按像素大小
    QFont mFont;                    // 文字使用的字体

    virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE;

};

#endif // CUSTOMBARS_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "custombars.h"
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
    CustomBars *minBar, *maxBar, *fossil;
public:
    void initBar();
    void addValue();
};

#endif // WIDGET_H

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liu Zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值