QwtPlot之绘制统计图
QwtPlot是用来绘制二维图像的widget。在它的画板上可以无限制的显示绘画组件。绘画组件可以是曲线(QwtPlotCurve)、标记(QwtPlotMarker)、网格(QwtPlotGrid)、或者其它从QwtPlotItem继承的组件。
QwtScaleDraw可以用来绘制线性或对数尺度。一个标尺可以指定位置、对齐方式、长度等。标签可使用setLabelRotation()和setLabelAlignment()来设置旋转和对齐方式。通过QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &s)设置独立的标尺QwtScaleDiv对象,标尺可以使用QwtAbstractScaleDraw::draw()函数来绘制。
看了一下QWT中关于distrowatch的代码,将其修改为天龙八部中十大高手排行榜,并添加了一些注释,排名是否正确先不做讨论,重在代码,^_^便于理解!
//barchar.h
#ifndef BAR_CHART_H
#define BAR_CHART_H
#include
class DistroChartItem;
class BarChart: public QwtPlot
{
Q_OBJECT
public:
BarChart(QWidget *parent = NULL);
public slots:
void setOrientation(int value);
void exportChart();
private:
void populate();
private:
DistroChartItem *d_barChartItem;
QStringList d_distros;
};
#endif //BAR_CHART_H
//barchar.cpp
#include "barchart.h"
#include
#include
#include
#include
#include
#include
#include
class DistroScaleDraw: public QwtScaleDraw
{
public:
DistroScaleDraw(Qt::Orientation orientation, const QStringList &labels)
: d_labels(labels)
{
//设置间距、中间刻度、主刻度
setTickLength(QwtScaleDiv::MinorTick, 0);
setTickLength(QwtScaleDiv::MediumTick, 0);
setTickLength(QwtScaleDiv::MajorTick, 5);
//不显示主轴线
enableComponent(QwtScaleDraw::Backbone, false);
//设置旋转角度、对齐方式
double rotation = (orientation == Qt::Vertical) ? -10.0 : -10.0;
setLabelRotation(rotation);
setLabelAlignment(Qt::AlignVCenter);
}
//用于显示文本
virtual QwtText label(double value) const
{
QwtText text("");
int index = static_cast(value); //qRound(value);
if (index >= 0 && index < d_labels.size())
text = d_labels[index];
return text;
}
private:
QStringList d_labels;
};
#include
class DistroChartItem: public QwtPlotBarChart
{
public:
DistroChartItem(): QwtPlotBarChart()
{
setLegendMode(QwtPlotBarChart::LegendBarTitles);
//设置项大小
setLegendIconSize(QSize(15, 15));
}
void addDistro(const QString &distro, const QColor &color )
{
d_colors += color;
d_distros += distro;
itemChanged();
}
//用于显示设置项
virtual QwtColumnSymbol *specialSymbol(int index, const QPointF &) const
{
//自定义项符号线度、样式、背景色
QwtColumnSymbol *symbol = new QwtColumnSymbol(QwtColumnSymbol::Box);
symbol->setLineWidth(5);
symbol->setFrameStyle(QwtColumnSymbol::Raised);
QColor color(Qt::white);
if (index >= 0 && index < d_colors.size())
color = d_colors[index];
symbol->setPalette(color);
return symbol;
}
//用于显示设置项文本
virtual QwtText barTitle(int sampleIndex) const
{
QwtText title("");
if (sampleIndex >= 0 && sampleIndex < d_distros.size())
title = d_distros[sampleIndex];
return title;
}
private:
QList d_colors;
QList d_distros;
};
BarChart::BarChart(QWidget *parent):
QwtPlot(parent)
{
const struct
{
QString distro;
int hits;
QColor color;
}
pageHits[] =
{
{QString::fromLocal8Bit("扫地神僧"), 10000, QColor(0, 160, 230)},
{QString::fromLocal8Bit("无崖子"), 9500, QColor(115, 185, 35)},
{QString::fromLocal8Bit("萧远山"), 8888, QColor(235, 30, 35)},
{QString::fromLocal8Bit("慕容博"), 8500, QColor(160, 70, 164)},
{QString::fromLocal8Bit("虚竹"), 8000, QColor(255, 130, 0)},
{QString::fromLocal8Bit("萧峰"), 7888, QColor(125, 125, 125)},
{QString::fromLocal8Bit("段誉"), 7000, QColor(125, 125, 255)},
{QString::fromLocal8Bit("天山童姥"), 6500, QColor(180, 255, 180)},
{QString::fromLocal8Bit("李秋水"), 5000, QColor(135, 205, 250)},
{QString::fromLocal8Bit("鸠摩智"), 4500, QColor(255, 175, 200)}
};
//设置标题、背景色
setAutoFillBackground(true);
setPalette(QColor("Linen"));
setTitle(QStringLiteral("天龙八部十大高手排行榜"));
//设置画布边框宽度、样式、圆角大小、背景色
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setLineWidth(2);
canvas->setFrameStyle(QFrame::Box | QFrame::Sunken);
canvas->setBorderRadius(10);
QPalette canvasPalette(QColor("Plum"));
canvasPalette.setColor(QPalette::Foreground, QColor("Indigo"));
canvas->setPalette(canvasPalette);
setCanvas(canvas);
d_barChartItem = new DistroChartItem();
QVector samples;
for (int i = 0; i < sizeof(pageHits) / sizeof(pageHits[0]); i++)
{
d_distros += pageHits[i].distro;
samples += pageHits[i].hits;
d_barChartItem->addDistro(pageHits[i].distro, pageHits[i].color);
}
d_barChartItem->setSamples(samples);
d_barChartItem->attach(this);
insertLegend(new QwtLegend());
setOrientation(0);
setAutoReplot(false);
}
void BarChart::setOrientation(int value)
{
//设置水平或垂直显示
Qt::Orientation orientation = (value == 0) ? Qt::Vertical : Qt::Horizontal;
int xBottomAxisId = QwtPlot::xBottom;
int yLeftAxisId = QwtPlot::yLeft;
if (orientation == Qt::Horizontal)
qSwap(xBottomAxisId, yLeftAxisId);
d_barChartItem->setOrientation(orientation);
//设置X/Y轴标题、显示范围、轴线的最大间隔
setAxisTitle(xBottomAxisId, QStringLiteral("人物"));
setAxisMaxMinor(xBottomAxisId, 3);
setAxisScale(xBottomAxisId, 0, d_barChartItem->dataSize() - 1, 1.0);
setAxisScaleDraw(xBottomAxisId, new DistroScaleDraw(orientation, d_distros));
setAxisTitle(yLeftAxisId, QStringLiteral("战斗力"));
setAxisScale(yLeftAxisId, 0, 10000);
setAxisMaxMinor(yLeftAxisId, 5);
setAxisScaleDraw(yLeftAxisId, new QwtScaleDraw());
//设置画布页边距
plotLayout()->setCanvasMargin(5);
//重新绘制
replot();
}
//导出pdf
void BarChart::exportChart()
{
QwtPlotRenderer renderer;
renderer.exportTo(this, QStringLiteral("天龙八部十大高手排行榜.pdf"));
}
//main.cpp
#include
#include
#include
#include
#include
#include "barchart.h"
class MainWindow: public QMainWindow
{
public:
MainWindow(QWidget *parent = NULL);
private:
BarChart *d_chart;
};
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent)
{
d_chart = new BarChart(this);
setCentralWidget(d_chart);
QToolBar *toolBar = new QToolBar(this);
QComboBox *orientationBox = new QComboBox(toolBar);
orientationBox->addItem("Vertical");
orientationBox->addItem("Horizontal");
orientationBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QToolButton *btnExport = new QToolButton(toolBar);
btnExport->setText("Export");
btnExport->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(btnExport, SIGNAL(clicked()), d_chart, SLOT(exportChart()));
toolBar->addWidget(orientationBox);
toolBar->addWidget(btnExport);
addToolBar(toolBar);
d_chart->setOrientation(orientationBox->currentIndex());
connect(orientationBox, SIGNAL(currentIndexChanged(int)), d_chart, SLOT(setOrientation(int)));
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow mainWindow;
mainWindow.resize(600, 500);
mainWindow.show();
return a.exec();
}
效果如下:
注:
技术在于交流、沟通,转载请注明出处并保持作品的完整性。