一、使用环境
三、自己改写代码
目的:在官网的例子上,改成多个柱子并排的
需要引入一个类 :QCPBars类
简单使用(2中方法):
QCPBars *bar = new QCPBars(this);
QCPBars *bar1 = new QCPBars(this);
QCPBarsGroup *group = new QCPBarsGroup(customPlot);
bar->setBarsGroup(group);
bar1->setBarsGroup(group);
//设置大小
bar->setWidth(0.3);
bar1->setWidth(0.3);
QCPBarsGroup *group = new QCPBarsGroup(customPlot);
QList bars;
bars << fossil << nuclear << regen;
foreach (QCPBars *bar, bars) {
// 设置柱状图的宽度类型为以key坐标轴计算宽度的大小,其实默认就是这种方式
bar->setWidthType(QCPBars::wtPlotCoords);
bar->setWidth(bar->width() / bars.size()); // 设置柱状图的宽度大小
group->append(bar); // 将柱状图加入柱状图分组中
}
上代码
.h
#pragma once
#include <QtWidgets/QWidget>
#include "ui_barchart.h"
#include "qcustomplot.h"
#include "custombars.h"
class BarChart : public QWidget
{
Q_OBJECT
public:
BarChart(QWidget *parent = 0);
private:
Ui::BarChartClass ui;
QCustomPlot *customPlot;
CustomBars *regen, *nuclear, *fossil;
};
.cpp
#include "barchart.h"
BarChart::BarChart(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
//整体布局
QHBoxLayout *m_h = new QHBoxLayout(this);
customPlot = new QCustomPlot(this);
m_h->addWidget(customPlot);
// set dark background gradient: 设置背景
QLinearGradient gradient(0, 0, 0, 400);
gradient.setColorAt(0, QColor(90, 90, 90));
gradient.setColorAt(0.38, QColor(105, 105, 105));
gradient.setColorAt(1, QColor(70, 70, 70));
customPlot->setBackground(QBrush(gradient));
// create empty bar chart objects:
regen = new CustomBars(customPlot->xAxis, customPlot->yAxis);
nuclear = new CustomBars(customPlot->xAxis, customPlot->yAxis);
fossil = new CustomBars(customPlot->xAxis, customPlot->yAxis);
QCPBarsGroup *group = new QCPBarsGroup(customPlot);
group->setSpacingType(QCPBarsGroup::stAbsolute); // 设置组内柱状图的间距,按像素
group->setSpacing(1); // 设置较小的间距值,这样看起来更紧凑
regen->setBarsGroup(group);
nuclear->setBarsGroup(group);
fossil->setBarsGroup(group);
//设置大小
regen->setWidth(0.3);
nuclear->setWidth(0.3);
fossil->setWidth(0.3);
//设置抗锯齿
regen->setAntialiased(false); // gives more crisp, pixel aligned bar borders
nuclear->setAntialiased(false);
fossil->setAntialiased(false);
// regen->setStackingGap(1);
// nuclear->setStackingGap(1);
// fossil->setStackingGap(1);
// set names and colors:
fossil->setName("Fossil fuels");
fossil->setPen(QPen(QColor(111, 9, 176).lighter(170)));
fossil->setBrush(QColor(111, 9, 176));
nuclear->setName("Nuclear");
nuclear->setPen(QPen(QColor(250, 170, 20).lighter(150)));
nuclear->setBrush(QColor(250, 170, 20));
regen->setName("Regenerative");
regen->setPen(QPen(QColor(0, 168, 140).lighter(130)));
regen->setBrush(QColor(0, 168, 140));
// // stack bars on top of each other:
// nuclear->moveAbove(fossil);
// regen->moveAbove(nuclear);
// prepare x axis with country labels:
QVector<double> ticks;
QVector<QString> labels;
ticks << 1 << 3 << 5 << 7 << 9 << 11 << 13;
labels << "USA" << "Japan" << "Germany" << "France" << "UK" << "Italy" << "Canada";
QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
textTicker->addTicks(ticks, labels);
customPlot->xAxis->setTicker(textTicker);
customPlot->xAxis->setTickLabelRotation(60);
customPlot->xAxis->setSubTicks(false);
customPlot->xAxis->setTickLength(0, 4);
customPlot->xAxis->setRange(0,15);
customPlot->xAxis->setBasePen(QPen(Qt::white));
customPlot->xAxis->setTickPen(QPen(Qt::white));
customPlot->xAxis->grid()->setVisible(true);
customPlot->xAxis->grid()->setPen(QPen(QColor(130, 130, 130), 0, Qt::DotLine));
customPlot->xAxis->setTickLabelColor(Qt::white);
customPlot->xAxis->setLabelColor(Qt::white);
// prepare y axis:
customPlot->yAxis->setRange(0, 12.1);
customPlot->yAxis->setPadding(5); // a bit more space to the left border
customPlot->yAxis->setLabel("Power Consumption in\nKilowatts per Capita (2007)");
customPlot->yAxis->setBasePen(QPen(Qt::white));
customPlot->yAxis->setTickPen(QPen(Qt::white));
customPlot->yAxis->setSubTickPen(QPen(Qt::white));
customPlot->yAxis->grid()->setSubGridVisible(true);
customPlot->yAxis->setTickLabelColor(Qt::white);
customPlot->yAxis->setLabelColor(Qt::white);
customPlot->yAxis->grid()->setPen(QPen(QColor(130, 130, 130), 0, Qt::SolidLine));
customPlot->yAxis->grid()->setSubGridPen(QPen(QColor(130, 130, 130), 0, Qt::DotLine));
// Add data:
QVector<double> fossilData, nuclearData, regenData;
fossilData << 0.86*10.5 << 0.83*5.5 << 0.84*5.5 << 0.52*5.8 << 0.89*5.2 << 0.90*4.2 << 0.67*11.2;
nuclearData << 0.08*10.5 << 0.12*5.5 << 0.12*5.5 << 0.40*5.8 << 0.09*5.2 << 0.00*4.2 << 0.07*11.2;
regenData << 0.06*10.5 << 0.05*5.5 << 0.04*5.5 << 0.06*5.8 << 0.02*5.2 << 0.07*4.2 << 0.25*11.2;
fossil->setData(ticks, fossilData);
nuclear->setData(ticks, nuclearData);
regen->setData(ticks, regenData);
// setup legend:
customPlot->legend->setVisible(true);
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop | Qt::AlignHCenter);
customPlot->legend->setBrush(QColor(255, 255, 255, 100));
customPlot->legend->setBorderPen(Qt::NoPen);
QFont legendFont = font();
legendFont.setPointSize(10);
customPlot->legend->setFont(legendFont);
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
}
显示数值的功能,是借助另外一个类去继承QCPBars
.h
#pragma once
#include
#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;
};
在这类中改写了QCPBars的draw函数
ps 注意一点 QRectF barRect = getBarRect(it->key, it->value); //自己加的
// 源文件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 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); //自己加的
painter->drawPolygon(barRect);
// 以上是拷贝的源码部分
painter->drawPolygon(barRect);
// 我们仅需在 painter->drawPolygon(barRect); 这行下增加以下的内容即可
// 计算文字的位置
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);
}
}
}
}
四、总结和感想