头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtCharts/QChartGlobal>
typedef QPair<QPointF, QString> Data;
typedef QList<Data> DataList;
typedef QList<DataList> DataTable;
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
QT_CHARTS_BEGIN_NAMESPACE
class QChartView;
class QChart;
QT_CHARTS_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private Q_SLOTS:
void on_themeComboBox_currentIndexChanged(int index); // 主题改变
void on_animatedComboBox_currentIndexChanged(int index); // 动画改变
void on_legendComboBox_currentIndexChanged(int index); // 注释说明位置改变
void on_antialiasCheckBox_stateChanged(int arg1); // 是否抗锯齿抗锯齿
private:
DataTable generateRandomData(int listCount, int valueMax, int valueCount) const;// 生成图表数据
void populateThemeBox(); // 初始化主题列表
void populateAnimationBox(); // 初始化动画列表
void populateLegendBox(); // 初始化注释说明位置列表
QChart *createAreaChart() const; // 创建面积图
QChart *createBarChart(int valueCount) const; // 创建柱状图
QChart *createPieChart() const; // 创建圆饼图
QChart *createLineChart() const; // 创建折线图
QChart *createSplineChart() const; // 创建曲线图
QChart *createScatterChart() const; // 创建分散图
private:
int mListCount; // 数据数量
int mValueMax; // 随机生成数据的最大值
int mValueCount;
QList<QChartView *> mCharts; // 图表集合列表
DataTable mDataTable; // 随机数据
Ui::Widget *ui;
};
#endif // WIDGET_H
实现文件
#include "widget.h"
#include "ui_widget.h"
#include <QChartView>
#include <QRandomGenerator>
#include <QLineSeries>
#include <QAreaSeries>
#include <QValueAxis>
#include <QStackedBarSeries>
#include <QBarSet>
#include <QPieSeries>
#include <QSplineSeries>
#include <QScatterSeries>
#include <QDebug>
#include <QComboBox>
Widget::Widget(QWidget *parent)
: QWidget(parent)
,mListCount(3)
,mValueMax(10)
,mValueCount(7)
,mDataTable(generateRandomData(mListCount, mValueMax, mValueCount))
,ui(new Ui::Widget)
{
ui->setupUi(this);
populateThemeBox();
populateAnimationBox();
populateLegendBox();
QChartView *chartView;
chartView = new QChartView(createAreaChart());
ui->gridLayout->addWidget(chartView, 1, 0);
mCharts << chartView;
chartView = new QChartView(createPieChart());
// QSizePolicy: 描述水平和垂直调整大小策略的布局属性, Ignored 部件将获得尽可能多的空间
chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
ui->gridLayout->addWidget(chartView, 1, 1);
mCharts << chartView;
chartView = new QChartView(createLineChart());
ui->gridLayout->addWidget(chartView, 1, 2);
mCharts << chartView;
chartView = new QChartView(createBarChart(mValueCount));
ui->gridLayout->addWidget(chartView, 2, 0);
mCharts << chartView;
chartView = new QChartView(createSplineChart());
ui->gridLayout->addWidget(chartView, 2, 1);
mCharts << chartView;
chartView = new QChartView(createScatterChart());
ui->gridLayout->addWidget(chartView, 2, 2);
mCharts << chartView;
ui->antialiasCheckBox->setChecked(true);
// 调色板
QPalette pal = qApp->palette();
pal.setColor(QPalette::Window, QRgb(0xf0f0f0)); // 背景色
pal.setColor(QPalette::WindowText, QRgb(0x404044)); // 前景色
qApp->setPalette(pal);
connect(ui->themeComboBox, SIGNAL(QComboBox::currentIndexChanged), this, SLOT(on_themeComboBox_currentIndexChanged));
connect(ui->animatedComboBox, SIGNAL(QComboBox::currentIndexChanged), this, SLOT(on_animatedComboBox_currentIndexChanged));
connect(ui->legendComboBox, SIGNAL(QComboBox::currentIndexChanged), this, SLOT(on_legendComboBox_currentIndexChanged));
connect(ui->antialiasCheckBox, SIGNAL(QCheckBox::stateChanged), this, SLOT(on_antialiasCheckBox_stateChanged));
//updateUI();
}
Widget::~Widget()
{
delete ui;
}
DataTable Widget::generateRandomData(int listCount, int valueMax, int valueCount) const
{
// QPair<QPointF, QString> Data;
// QList<Data> DataList;
// QList<DataList> DataTable;
DataTable dataTable;
for (int i = 0; i < listCount; i++) {
DataList dataList;
qreal yValue(0);
for (int j = 0; j < valueCount; j++) {
yValue = yValue + QRandomGenerator::global()->bounded(valueMax / (qreal)valueCount);
QPointF value((j + QRandomGenerator::global()->generateDouble()) * ((qreal)mValueMax / (qreal)valueCount), yValue);
QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
dataList << Data(value, label);
}
dataTable << dataList;
}
return dataTable;
}
void Widget::populateThemeBox()
{
ui->themeComboBox->addItem("Light", QChart::ChartThemeLight);
ui->themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
ui->themeComboBox->addItem("Dark", QChart::ChartThemeDark);
ui->themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
ui->themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
ui->themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
ui->themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
ui->themeComboBox->addItem("Qt", QChart::ChartThemeQt);
}
void Widget::populateAnimationBox()
{
ui->animatedComboBox->addItem("No Animations", QChart::NoAnimation);
ui->animatedComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
ui->animatedComboBox->addItem("Series Animations", QChart::SeriesAnimations);
ui->animatedComboBox->addItem("ALl Animations", QChart::AllAnimations);
}
void Widget::populateLegendBox()
{
ui->legendComboBox->addItem("No Legend", 0);
ui->legendComboBox->addItem("Legend Top", Qt::AlignTop);
ui->legendComboBox->addItem("Legend Bottom", Qt::AlignBottom);
ui->legendComboBox->addItem("Legend Left", Qt::AlignLeft);
ui->legendComboBox->addItem("Legend Right", Qt::AlignRight);
}
/**
* 面积图表
* @brief Widget::createAreaChart
* @return
*/
QChart *Widget::createAreaChart() const
{
QChart *chart = new QChart();
chart->setTitle("Area chart");
QLineSeries *lowerSeries = 0;
QString name("Series ");
int nameIndex = 0;
for (int i(0); i < mDataTable.count(); i++) {
QLineSeries *upperSeries = new QLineSeries(chart);
for (int j(0); j < mDataTable[i].count(); j++) {
Data data = mDataTable[i].at(j);
if (lowerSeries) {
// QPointF表示一个平面上整数精度的点坐标,可以通过x(),y()等函数方便的进行存取操作
const QVector<QPointF> &points = lowerSeries->pointsVector();
upperSeries->append(QPointF(j, points[i].y() + data.first.y()));
} else {
upperSeries->append(QPointF(j, data.first.y()));
}
}
QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
area->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(area);
lowerSeries = upperSeries;
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, mValueCount - 1);
chart->axes(Qt::Vertical).first()->setRange(0, mValueMax);
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
QChart *Widget::createBarChart(int valueCount) const
{
Q_UNUSED(valueCount);
QChart *chart = new QChart();
chart->setTitle("Bar chart");
QStackedBarSeries *series = new QStackedBarSeries(chart);
for (int i(0); i < mDataTable.count(); i++) {
QBarSet *set = new QBarSet("Bar set " + QString::number(i));
for (const Data &data : mDataTable[i]) {
*set << data.first.y();
}
series->append(set);
}
chart->addSeries(series);
chart->createDefaultAxes();
chart->axes(Qt::Vertical).first()->setRange(0, mValueMax * 2);
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
QChart *Widget::createLineChart() const
{
QChart *chart = new QChart();
chart->setTitle("Line chart");
QString name("Series ");
int nameIndex = 0;
for (const DataList &list : mDataTable) {
QLineSeries *series = new QLineSeries(chart);
for (const Data &data : list) {
series->append(data.first);
}
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, mValueMax);
chart->axes(Qt::Vertical).first()->setRange(0, mValueCount);
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
QChart *Widget::createPieChart() const
{
QChart *chart = new QChart();
chart->setTitle("Pie chart");
QPieSeries *series = new QPieSeries(chart);
for (const Data &data : mDataTable[0]) {
QPieSlice *slice = series->append(data.second, data.first.y());
if (data == mDataTable[0].first()) {
slice->setLabelVisible();
slice->setExploded();
slice->setExplodeDistanceFactor(0.5);
}
}
series->setPieSize(0.4);
chart->addSeries(series);
return chart;
}
QChart *Widget::createSplineChart() const
{
QChart *chart = new QChart();
chart->setTitle("Spline chart");
QString name("Series ");
int nameIndex = 0;
for (const DataList &list : mDataTable) {
QSplineSeries *series = new QSplineSeries(chart);
for (const Data &data : list) {
series->append(data.first);
}
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, mValueMax);
chart->axes(Qt::Vertical).first()->setRange(0, mValueCount);
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%0.1f" );
return chart;
}
QChart *Widget::createScatterChart() const
{
QChart *chart = new QChart();
chart->setTitle("Scatter chart");
QString name("Series ");
int nameIndex = 0;
for (const DataList &list : mDataTable) {
QScatterSeries *series = new QScatterSeries(chart);
for (const Data &data : list) {
series->append(data.first);
}
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, mValueMax);
chart->axes(Qt::Vertical).first()->setRange(0, mValueCount);
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%0.1f" );
return chart;
}
void Widget::on_themeComboBox_currentIndexChanged(int index)
{
QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(ui->themeComboBox->itemData(index).toInt());
const auto charts = mCharts;
if (!mCharts.isEmpty() && mCharts.at(0)->chart()->theme() != theme) {
for (QChartView *chartView : charts) {
chartView->chart()->setTheme(theme);
}
QPalette pal = window()->palette();
if (theme == QChart::ChartThemeLight) {
pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else if (theme == QChart::ChartThemeDark) {
pal.setColor(QPalette::Window, QRgb(0x121218));
pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
} else if (theme == QChart::ChartThemeBlueCerulean) {
pal.setColor(QPalette::Window, QRgb(0x40434a));
pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
} else if (theme == QChart::ChartThemeBrownSand) {
pal.setColor(QPalette::Window, QRgb(0x9e8965));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else if (theme == QChart::ChartThemeBlueNcs) {
pal.setColor(QPalette::Window, QRgb(0x018bba));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else if (theme == QChart::ChartThemeHighContrast) {
pal.setColor(QPalette::Window, QRgb(0xffab03));
pal.setColor(QPalette::WindowText, QRgb(0x181818));
} else if (theme == QChart::ChartThemeBlueIcy) {
pal.setColor(QPalette::Window, QRgb(0xcee7f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else {
pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
}
window()->setPalette(pal);
}
}
void Widget::on_animatedComboBox_currentIndexChanged(int index)
{
const auto charts = mCharts;
QChart::AnimationOptions options(ui->animatedComboBox->itemData(index).toInt());
if (!mCharts.isEmpty() && mCharts.at(0)->chart()->animationOptions() != options) {
for (QChartView *chartView : charts) {
chartView->chart()->setAnimationOptions(options);
}
}
}
void Widget::on_legendComboBox_currentIndexChanged(int index)
{
const auto charts = mCharts;
Qt::Alignment alignment(ui->legendComboBox->itemData(ui->legendComboBox->currentIndex()).toInt());
if (!alignment) {
for (QChartView *chartView : charts) {
chartView->chart()->legend()->hide();
}
} else {
for (QChartView *chartView : charts) {
chartView->chart()->legend()->setAlignment(alignment);
chartView->chart()->legend()->show();
}
}
}
void Widget::on_antialiasCheckBox_stateChanged(int arg1)
{
const auto charts = mCharts;
bool checked = ui->antialiasCheckBox->isChecked();
for (QChartView *chart : charts) {
chart->setRenderHint(QPainter::Antialiasing, checked);
}
}
最终效果