九、Qt图表使用

一、QCharts概述

Qt图表提供了:折线图、样条曲线图、面积图、散点图、条形图、饼图、方块胡须图、蜡烛图、极坐标图。

1、QChart介绍

Qt Charts基于Qt的QGraphics View架构,其核心组件是QChartView和QChart
  • QChartView是显示图标的视图,基类为QGraphicsView
  • QChart的基类是QGraphicsItem
QGraphicsItem
	QGraphicsObject
		QGraphicsWidget
			QChart

2、使用

(1)项目管理

在使用Qt Charts模块,必须在项目中配置
QT += charts

(2)类中使用QCharts

在类中使用QCharts,需要在头文件或者源文件分别添加:
#include <QtCharts>
// using namespace QtCharts;
QT_CHARTS_USE_NAMESPACE // 使用宏代替

3、实现程序

(1)创建项目,基于QMainWindow

(2)实现图表

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QChartView>
QT_CHARTS_USE_NAMESPACE
#include <QLineSeries>
#include <QtMath>
#include <QValueAxis>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
   
    ui->setupUi(this);

    // 创建图标
    QChartView *chartView = new QChartView(this);
    QChart *chart = new QChart();
    chart->setTitle("简单函数曲线");
    chartView->setChart(chart);
    setCentralWidget(chartView);

    // 创建曲线序列
    QLineSeries *series0 = new QLineSeries;
    QLineSeries *series1 = new QLineSeries;
    series0->setName("Sin曲线");
    series1->setName("Cos曲线");
    chart->addSeries(series0);
    chart->addSeries(series1);

    qreal y0, y1, t = 0, intv = 0.1/*时间间隔*/;
    int cnt = 100;

    for (int i = 0; i < cnt; ++i)
    {
   
        y0 = qSin(t);
        series0->append(t, y0);
        y1 = qCos(t);
        series1->append(t, y1);
        t += intv;
    }

    //创建坐标轴
    QValueAxis *axisX = new QValueAxis;
    axisX->setRange(0, 10);
    chart->setAxisX(axisX, series0);
    chart->setAxisX(axisX, series1);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(-1, 1);
    chart->setAxisY(axisY, series0);
    chart->setAxisY(axisY, series1);
}

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

在这里插入图片描述

二、QChart绘制折线图

1、类继承关系

(1)数据序列类

QAbractSeries
	QAreaSeries
	QBoxPlotSeries
	QAbstractBarSeries
		QBarSeries
		QHorizontalBarSeries
		QHorizontalStackedBarSeries
		QPercentBarSeries
		QStackedBarSeries
	QPieSeries
	QXYSeties
		QLineSeries
			QSplineSeries
		QScatterSeries

(2)坐标轴类

QAbstractAxis
	QValuesAxis
		QCategoryAxis
	QLogValueAxis
	QBarCategoryAxis
	QDataTimeAxis

2、实现程序

在这里插入图片描述

(1)创建项目, 基于QMainwindow

(2)QScrollArea 滚动条

在这里插入图片描述
在这里插入图片描述

(3)添加组件

在这里插入图片描述

(4)添设置画笔的UI和类

在这里插入图片描述

#include "dialogpen.h"
#include "ui_dialogpen.h"

DialogPen::DialogPen(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogPen)
{
   
    ui->setupUi(this);

    ui->comboBoxLineType->clear();
    ui->comboBoxLineType->addItem("NoPen", 0);
    ui->comboBoxLineType->addItem("SolidLine", 1);
    ui->comboBoxLineType->addItem("DashLine", 2);
    ui->comboBoxLineType->addItem("DotLine", 3);
    ui->comboBoxLineType->addItem("DashDotLine", 4);
    ui->comboBoxLineType->addItem("DashDotDotLine", 5);
    ui->comboBoxLineType->addItem("CustomDashLine", 6);

    ui->comboBoxLineType->setCurrentIndex(1);
}

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

QPen DialogPen::getPen()
{
   
    m_pen.setStyle(Qt::PenStyle(ui->comboBoxLineType->currentIndex()));
    m_pen.setWidth(ui->spinBoxLineWidth->value());
    QColor color = ui->btnLineColor->palette().color(QPalette::Button);
    m_pen.setColor(color);
    return m_pen;
}

QPen DialogPen::getPen(QPen initPen, bool &ok)
{
   
    QPen pen;
    DialogPen *dlg = new DialogPen;
    dlg->setPen(initPen);
    int ret = dlg->exec();

    if(ret == QDialog::Accepted)
    {
   
        pen = dlg->getPen();
        ok = true;
    }
    else
    {
   
        pen = initPen;
        ok = false;
    }

    delete dlg;
    return pen;
}

void DialogPen::setPen(const QPen &pen)
{
   
    m_pen = pen;
    ui->spinBoxLineWidth->setValue(pen.width());
    int nType = static_cast<int>(pen.style());
    ui->comboBoxLineType->setCurrentIndex(nType);
    ui->btnLineColor->setAutoFillBackground(true);

    QColor color = pen.color();
    QString str = QString::asprintf("background-color: rgb(%d,%d,%d)",
                                    color.red(), color.green(), color.blue());
    ui->btnLineColor->setStyleSheet(str);
}

#include <QColorDialog>
void DialogPen::on_btnLineColor_clicked()
{
   
    QColor color = m_pen.color();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        QString str = QString::asprintf("background-color: rgb(%d,%d,%d)",
                                        color.red(), color.green(), color.blue());
        ui->btnLineColor->setStyleSheet(str);
    }
}

(5)初始化图表

void MainWindow::createChart()
{
   
    QChart*chart = new QChart();
    chart->setTitle("简单的曲线");
    ui->chartView->setChart(chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing); // 抗锯齿

    QLineSeries *series0 = new QLineSeries;
    QLineSeries *series1 = new QLineSeries;

    series0->setName("Sin曲线");
    series1->setName("Cos曲线");
    curSeries = series0;

    QPen pen;
    pen.setStyle(Qt::DotLine);
    pen.setWidth(2);
    pen.setColor(Qt::red);
    series0->setPen(pen);

    pen.setStyle(Qt::SolidLine);
    pen.setColor(Qt::blue);
    series1->setPen(pen);

    chart->addSeries(series0);
    chart->addSeries(series1);

    QValueAxis *axisX = new QValueAxis;
    QValueAxis *axisY = new QValueAxis;
    curAxis = axisX;

    axisX->setRange(0, 10);
    axisX->setLabelFormat("%0.1f");
    axisX->setTickCount(11); // 大格间隔数
    axisX->setMinorTickCount(4); // 小格间隔数
    axisX->setTitleText("time(secs)");

    axisY->setRange(-1.2, 1.2);
    axisY->setTickCount(3); // 大格间隔数
    axisY->setMinorTickCount(4); // 小格间隔数
    axisY->setTitleText("value");

    chart->setAxisX(axisX, series0);
    chart->setAxisX(axisX, series1);
    chart->setAxisY(axisY, series0);
    chart->setAxisY(axisY, series1);
}```
### (6)绘制曲线

```bash
void MainWindow::prepareData()
{
   
    QLineSeries *series0 = (QLineSeries*)ui->chartView->chart()->series().at(0);
    QLineSeries *series1 = (QLineSeries*)ui->chartView->chart()->series().at(1);
    int cnt = 100;
    series0->clear();
    series1->clear();

    qsrand(QTime::currentTime().second());
    qreal t = 0, y0 = 0, y1 = 0, intv = 0.1;
    qreal rd;

    for (int i = 0; i < cnt; ++i)
    {
   
        rd = (qrand() % 10 - 5);
        y0 = qSin(t) + rd / 50;
        series0->append(t, y0);
        y1 = qCos(t) + rd / 50;
        series1->append(t, y1);
        t += intv;
    }
}

(6)实现组件功能

#include "mainwindow.h"

#include <qchartview.h>
#include "ui_mainwindow.h"
#include "dialogpen.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
   
    ui->setupUi(this);

    createChart();
    prepareData();
    updateFromChart();
}

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

void MainWindow::createChart()
{
   
    QChart*chart = new QChart();
    chart->setTitle("简单的曲线");
    ui->chartView->setChart(chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing); // 抗锯齿

    QLineSeries *series0 = new QLineSeries;
    QLineSeries *series1 = new QLineSeries;

    series0->setName("Sin曲线");
    series1->setName("Cos曲线");
    curSeries = series0;

    QPen pen;
    pen.setStyle(Qt::DotLine);
    pen.setWidth(2);
    pen.setColor(Qt::red);
    series0->setPen(pen);

    pen.setStyle(Qt::SolidLine);
    pen.setColor(Qt::blue);
    series1->setPen(pen);

    chart->addSeries(series0);
    chart->addSeries(series1);

    QValueAxis *axisX = new QValueAxis;
    QValueAxis *axisY = new QValueAxis;
    curAxis = axisX;

    axisX->setRange(0, 10);
    axisX->setLabelFormat("%0.1f");
    axisX->setTickCount(11); // 大格间隔数
    axisX->setMinorTickCount(4); // 小格间隔数
    axisX->setTitleText("time(secs)");

    axisY->setRange(-1.2, 1.2);
    axisY->setTickCount(3); // 大格间隔数
    axisY->setMinorTickCount(4); // 小格间隔数
    axisY->setTitleText("value");

    chart->setAxisX(axisX, series0);
    chart->setAxisX(axisX, series1);
    chart->setAxisY(axisY, series0);
    chart->setAxisY(axisY, series1);
}

#include <QTime>
void MainWindow::prepareData()
{
   
    QLineSeries *series0 = (QLineSeries*)ui->chartView->chart()->series().at(0);
    QLineSeries *series1 = (QLineSeries*)ui->chartView->chart()->series().at(1);
    int cnt = 100;
    series0->clear();
    series1->clear();

    qsrand(QTime::currentTime().second());
    qreal t = 0, y0 = 0, y1 = 0, intv = 0.1;
    qreal rd;

    for (int i = 0; i < cnt; ++i)
    {
   
        rd = (qrand() % 10 - 5);
        y0 = qSin(t) + rd / 50;
        series0->append(t, y0);
        y1 = qCos(t) + rd / 50;
        series1->append(t, y1);
        t += intv;
    }
}

void MainWindow::updateFromChart()
{
   
    QChart *chart = ui->chartView->chart();
    ui->lineEditTitle->setText(chart->title());

    QMargins mg = chart->margins();
    ui->spinBoxUp->setValue(mg.top());
    ui->spinBoxDown->setValue(mg.bottom());
    ui->spinBoxLeft->setValue(mg.left());
    ui->spinBoxRight->setValue(mg.right());


}

void MainWindow::on_actZoomIn_triggered()
{
   
    ui->chartView->chart()->zoom(1.2);
}

void MainWindow::on_actZoomOut_triggered()
{
   
    ui->chartView->chart()->zoom(0.8);
}

void MainWindow::on_actDraw_triggered()
{
   
    prepareData();
}

void MainWindow::on_actZoomReset_triggered()
{
   
    ui->chartView->chart()->zoomReset();
}

void MainWindow::on_btnLinePen_clicked()
{
   
    QPen pen = curSeries->pen();
    bool ok = false;
    pen = DialogPen::getPen(pen, ok);

    if(ok)
    {
   
        curSeries->setPen(pen);
    }
}

void MainWindow::on_btnSetTitle_clicked()
{
   
    QString strTitle =  ui->lineEditTitle->text();
    QChart *chart = ui->chartView->chart();
    chart->setTitle(strTitle);
}

void MainWindow::on_btnSetTitleFont_clicked()
{
   
    QFont font = ui->chartView->chart()->titleFont();
    bool ok;
    font = QFontDialog::getFont(&ok, font);

    if(ok)
    {
   
        ui->chartView->chart()->setTitleFont(font);
    }
}

void MainWindow::on_rbtnUp_clicked()
{
   
    ui->chartView->chart()->legend()->setAlignment(Qt::AlignTop);
}

void MainWindow::on_rbtnDown_clicked()
{
   
    ui->chartView->chart()->legend()->setAlignment(Qt::AlignBottom);
}

void MainWindow::on_rbtnLeft_clicked()
{
   
    ui->chartView->chart()->legend()->setAlignment(Qt::AlignLeft);
}

void MainWindow::on_rbtnRight_clicked()
{
   
    ui->chartView->chart()->legend()->setAlignment(Qt::AlignRight);
}

void MainWindow::on_checkBoxName_clicked(bool checked)
{
   
    ui->chartView->chart()->legend()->setVisible(checked);
}

void MainWindow::on_checkBoxBack_clicked(bool checked)
{
   
    ui->chartView->chart()->legend()->setBackgroundVisible(checked);
}

void MainWindow::on_btnNameFont_clicked()
{
   
    QFont font = ui->chartView->chart()->legend()->font();
    bool ok;
    font = QFontDialog::getFont(&ok, font);

    if(ok)
    {
   
        ui->chartView->chart()->legend()->setFont(font);
    }
}

void MainWindow::on_btnNameColor_clicked()
{
   
    QColor color = ui->chartView->chart()->legend()->labelColor();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        ui->chartView->chart()->legend()->setLabelColor(    color);
    }
}

void MainWindow::on_btnSetMargin_clicked()
{
   
    QMargins mg;
    mg.setTop(ui->spinBoxUp->value());
    mg.setBottom(ui->spinBoxDown->value());
    mg.setLeft(ui->spinBoxLeft->value());
    mg.setRight(ui->spinBoxRight->value());
    ui->chartView->chart()->setMargins(mg);
}

void MainWindow::on_comboBoxAction_currentIndexChanged(int index)
{
   
    ui->chartView->chart()->setAnimationOptions((QChart::AnimationOptions)index);
}

void MainWindow::on_comboBoxTheme_currentIndexChanged(int index)
{
    ui->chartView->chart()->setTheme((QChart::ChartTheme)index);
}

void MainWindow::on_rbtnSeriesSin_clicked()
{
    if( ui->rbtnSeriesSin->isChecked())
    {
   
        curSeries = (QLineSeries*)ui->chartView->chart()->series().at(0);
    }
    else
    {
   
        curSeries = (QLineSeries*)ui->chartView->chart()->series().at(1);
    }

    ui->lineEditLine->setText(curSeries->name());
    ui->checkBoxSeries->setChecked(curSeries->isVisible());
    ui->checkBoxDataPoint->setChecked(curSeries->pointsVisible());
    ui->horizontalSlider->setValue(curSeries->opacity() * 10); // 0-1 => 0-10
    ui->checkBoxPointTip->setChecked(curSeries->pointLabelsVisible());
}

void MainWindow::on_rbtnSeriesCos_clicked()
{
   
    if( ui->rbtnSeriesSin->isChecked())
    {
   
        curSeries = (QLineSeries*)ui->chartView->chart()->series().at(0);
    }
    else
    {
   
        curSeries = (QLineSeries*)ui->chartView->chart()->series().at(1);
    }

    ui->lineEditLine->setText(curSeries->name());
    ui->checkBoxSeries->setChecked(curSeries->isVisible());
    ui->checkBoxDataPoint->setChecked(curSeries->pointsVisible());
    ui->horizontalSlider->setValue(curSeries->opacity() * 10); // 0-1 => 0-10
    ui->checkBoxPointTip->setChecked(curSeries->pointLabelsVisible());
}

void MainWindow::on_btnLineName_clicked()
{
   
    curSeries->setName(ui->lineEditLine->text());
}

void MainWindow::on_checkBoxSeries_clicked(bool checked)
{
   
    curSeries->setVisible(checked);
}

void MainWindow::on_checkBoxDataPoint_clicked(bool checked)
{
   
    curSeries->setPointLabelsVisible(checked);
}

void MainWindow::on_btnLineColor_clicked()
{
   
    QColor color = curSeries->color();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        curSeries->setColor(color);
    }
}

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
   
    curSeries->setOpacity(value / 10.0);
}

void MainWindow::on_checkBoxPointTip_clicked(bool checked)
{
   
    curSeries->setPointLabelsVisible(checked);
}

void MainWindow::on_btnPointTipColor_clicked()
{
   
    QColor color = curSeries->pointLabelsColor();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        curSeries->setPointLabelsColor(color);
    }
}

void MainWindow::on_btnPointTipFont_clicked()
{
   
    QFont font = curSeries->pointLabelsFont();
    bool ok;
    font = QFontDialog::getFont(&ok, font);

    if(ok)
    {
   
        curSeries->setPointLabelsFont(font);
    }
}

void MainWindow::on_rbtnDisplayX_clicked()
{
   
    if(ui->rbtnDisplayX->isChecked())
    {
   
        curSeries->setPointLabelsFormat("@yPoint");
    }
    else
    {
   
        curSeries->setPointLabelsFormat("(@xPoint,@yPoint)");
    }
}

void MainWindow::on_rbtnDisplayXY_clicked()
{
   
    if(ui->rbtnDisplayX->isChecked())
    {
   
        curSeries->setPointLabelsFormat("@yPoint");
    }
    else
    {
   
        curSeries->setPointLabelsFormat("(@xPoint,@yPoint)");
    }
}

void MainWindow::on_rbtnSetX_clicked()
{
   
    QList<QAbstractAxis*> axes;

    if(ui->rbtnSetX->isChecked())
    {
   
        axes = ui->chartView->chart()->axes(Qt::Horizontal);
    }
    else
    {
   
        axes = ui->chartView->chart()->axes(Qt::Vertical);
    }

    curAxis = (QValueAxis*)axes[0];

    ui->doubleSpinBoxMin->setValue(curAxis->min());
    ui->doubleSpinBoxMax->setValue(curAxis->max());

    ui->lineEditAxisTitle->setText(curAxis->titleText());
    ui->checkBoxAxisTitleIsVisibe->setChecked(curAxis->isTitleVisible());

    ui->lineEditFormat->setText(curAxis->labelFormat());
    ui->checkBoxAxisTitleIsVisibe->setChecked(curAxis->labelsVisible());

    ui->checkBoxIsGridLineVisible->setChecked(curAxis->isGridLineVisible());
    ui->checkBoxisLineVisible->setChecked(curAxis->isLineVisible());

    ui->spinBoxTick->setValue(curAxis->tickCount());
    ui->checkBoxisLineVisible->setChecked(curAxis->isLineVisible());

    ui->spinBoxMinorTick->setValue(curAxis->minorTickCount());
    ui->checkBoxIsMinorGirdLineVisible->setChecked(curAxis->isMinorGridLineVisible());
}

void MainWindow::on_rbtnSetY_clicked()
{
   
    QList<QAbstractAxis*> axes;

    if(ui->rbtnSetX->isChecked())
    {
   
        axes = ui->chartView->chart()->axes(Qt::Horizontal);
    }
    else
    {
   
        axes = ui->chartView->chart()->axes(Qt::Vertical);
    }

    curAxis = (QValueAxis*)axes[0];

    ui->doubleSpinBoxMin->setValue(curAxis->min());
    ui->doubleSpinBoxMax->setValue(curAxis->max());

    ui->lineEditAxisTitle->setText(curAxis->titleText());
    ui->checkBoxAxisTitleIsVisibe->setChecked(curAxis->isTitleVisible());

    ui->lineEditFormat->setText(curAxis->labelFormat());
    ui->checkBoxAxisTitleIsVisibe->setChecked(curAxis->labelsVisible());

    ui->checkBoxIsGridLineVisible->setChecked(curAxis->isGridLineVisible());
    ui->checkBoxisLineVisible->setChecked(curAxis->isLineVisible());

    ui->spinBoxTick->setValue(curAxis->tickCount());
    ui->checkBoxisLineVisible->setChecked(curAxis->isLineVisible());

    ui->spinBoxMinorTick->setValue(curAxis->minorTickCount());
    ui->checkBoxIsMinorGirdLineVisible->setChecked(curAxis->isMinorGridLineVisible());
}

void MainWindow::on_checkBoxIsVisible_clicked(bool checked)
{
   
    curAxis->setVisible(checked);
}

void MainWindow::on_btnSetAxisRange_clicked()
{
   
    curAxis->setRange(ui->doubleSpinBoxMin->value(), ui->doubleSpinBoxMax->value());
}

void MainWindow::on_btnSetAxisTitle_clicked()
{
   
    curAxis->setTitleText(ui->lineEditAxisTitle->text());
}

void MainWindow::on_checkBoxAxisTitleIsVisibe_clicked(bool checked)
{
   
    curAxis->setTitleVisible(checked);
}

void MainWindow::on_btnAxisTitleFont_clicked()
{
   
    QFont font = curAxis->titleFont();
    bool ok;
    font = QFontDialog::getFont(&ok, font);

    if(ok)
    {
   
        curAxis->setTitleFont(font);
    }
}

void MainWindow::on_btnSetFormat_clicked()
{
   
    curAxis->setLabelFormat(ui->lineEditFormat->text());
}

void MainWindow::on_btnSetColor_clicked()
{
   
    QColor color = curAxis->labelsColor();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        curAxis->setLabelsColor(color);
    }
}

void MainWindow::on_btnSetFont_clicked()
{
   
    QFont font = curAxis->labelsFont();
    bool ok;
    font = QFontDialog::getFont(&ok, font);

    if(ok)
    {
   
        curAxis->setLabelsFont(font);
    }
}

void MainWindow::on_checkBoxlabelVisible_clicked(bool checked)
{
   
    curAxis->setLabelsVisible(checked);
}

void MainWindow::on_checkBoxIsGridLineVisible_clicked(bool checked)
{
   
    curAxis->setLineVisible(checked);
}

void MainWindow::on_btnGridLineColor_clicked()
{
   
    QColor color = curAxis->gridLineColor();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        curAxis->setGridLineColor(color);
    }
}

void MainWindow::on_btnGridLinePen_clicked()
{
   
    QPen pen = curAxis->gridLinePen();
    bool ok = false;
    pen = DialogPen::getPen(pen, ok);

    if(ok)
    {
   
        curAxis->setGridLinePen(pen);
    }
}

void MainWindow::on_checkBoxIsMinorGirdLineVisible_clicked(bool checked)
{
   
    curAxis->setMinorGridLineVisible(checked);
}

void MainWindow::on_btnMinorGridLineColor_clicked()
{
   
    QColor color = curAxis->minorGridLineColor();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        curAxis->setMinorGridLineColor(color);
    }
}

void MainWindow::on_btnMinorGirdLinePen_clicked()
{
   
    QPen pen = curAxis->minorGridLinePen();
    bool ok = false;
    pen = DialogPen::getPen(pen, ok);

    if(ok)
    {
   
        curAxis->setMinorGridLinePen(pen);
    }
}

void MainWindow::on_spinBoxMinorTick_valueChanged(int arg1)
{
   
    curAxis->setMinorTickCount(arg1);
}

void MainWindow::on_btnLinePen_2_clicked()
{
   
    QPen pen = curAxis->linePen();
    bool ok = false;
    pen = DialogPen::getPen(pen, ok);

    if(ok)
    {
   
        curAxis->setLinePen(pen);
    }
}

void MainWindow::on_spinBoxTick_valueChanged(int arg1)
{
   
    curAxis->setTickCount(arg1);
}

void MainWindow::on_btnLinePenColor_clicked()
{
   
    QColor color = curAxis->linePenColor();
    color = QColorDialog::getColor(color);

    if(color.isValid())
    {
   
        curAxis->setLinePenColor(color);
    }
}

三、QChart常见图表绘制

1、图表与类

(1)柱状图

  • QBarSet:数据集
  • QBarSeries:一个序列可以包含多个QBarSet
  • QBarCategoryAxis:横坐标轴
  • QValueAxis:纵坐标轴

(2)饼状图

  • QPieSeries:数据序列
  • QPieSlice:饼图扇区

(3)堆叠柱状图

  • QBarSet:数据集
  • QStackedBarSeries:一个序列可以有多个QBarSet
  • QBarCategoryAxis:横坐标
  • QValueAxis:纵坐标轴

(4)百分比柱状图

  • QBarSet:数据集
  • QPercentageBarSeries:一个序列可以有多个QBarSet
  • QBarCategoryAxis:横坐标
  • QValueAxis:纵坐标轴

(5)散点图和光滑曲线

  • QSplineSeries、QLineSeries:散点和平滑线
  • QValueAxis:坐标轴。

2、实现程序

在这里插入图片描述

(1)创建项目,基于QMainWindows

(2)添加图表资源文件,添加工具栏

(3)添加组件

在这里插入图片描述

(4)柱状图

在这里插入图片描述

void MainWindow::initBarChart()
{
   
    QChart *chart = new QChart;
    chart->setTitle("BarChart演示");
    chart->setAnimationOptions(QChart::SeriesAnimations);
    ui->cvChartBar->setChart(chart);
    ui->cvChartBar->setRenderHint(QPainter::Antialiasing);
}

void MainWindow::buildBarChart()
{
   
    QChart *chart = ui->cvChartBar->chart();
    chart->removeAllSeries();

    if(chart->axisX() != nullptr)
    {
   
        chart->removeAxis(chart->axisX());
    }

    if(chart->axisY() != nullptr)
    {
   
        chart->removeAxis(chart->axisY());
    }

    // 数据集
    QBarSet *setMath = new QBarSet(theModel->horizontalHeaderItem(colNoMath)->text());
    QBarSet *setChinese = new QBarSet(theModel->horizontalHeaderItem(colNoChinese)->text());
    QBarSet *setEnglish = new QBarSet(theModel->horizontalHeaderItem(colNoEnglish)->text());
    QLineSeries *lineAverage = new QLineSeries;
    lineAverage->setName(theModel->horizontalHeaderItem(colNoAverage)->text());
    QPen pen;
    pen.setColor(Qt::red);
    pen.setWidth(2);
    lineAverage->setPen(pen);


    for (int i = 0; i < theModel->rowCount(); ++i)
    {
   
        setMath->append(theModel->item(i, colNoMath)->text().toInt());
        setChinese->append(theModel->item(i, colNoChinese)->text().toInt());
        setEnglish->append(theModel->item(i, colNoEnglish)->text().toInt());
        lineAverage->append(QPointF(i, theModel->item(i, colNoAverage)->text().toFloat()));
    }

    // 序列
    QBarSeries *series = new QBarSeries;
    series->append(setMath);
    series->append(setChinese);
    series->append(setEnglish);

    chart->addSeries(series);
    chart->addSeries(lineAverage);
    chart->legend()->setAlignment(Qt::AlignBottom);

    QStringList category;

    for (int i = 0; i < theModel->rowCount(); ++i)
    {
   
        category << theModel->item(i, colNoName)->text();
    }

    QBarCategoryAxis *axisX = new QBarCategoryAxis;
    axisX->setCategories(category);
    chart->setAxisX(axisX, series);
    chart->setAxisX(axisX, lineAverage);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0, 100);
    axisY->setTitleText("分数");
    chart->setAxisY(axisY, series);
    chart->setAxisY(axisY, lineAverage);
}

(5)饼状图

在这里插入图片描述

void MainWindow::initPieChart()
{
   
    QChart *chart = new QChart;
    chart->setTitle("PieChart演示");
    chart->setAnimationOptions(QChart::SeriesAnimations);
    ui->cvPieChart->setChart(chart);
    ui->cvPieChart->setRenderHint(QPainter::Antialiasing);
}

void MainWindow::buildPieChart()
{
   
    QChart *chart = ui->cvPieChart->chart();
    chart->removeAllSeries();

    if(chart->axisX() != nullptr)
    {
   
        chart->removeAxis(chart->axisX());
    }

    if(chart->axisY() != nullptr)
    {
   
        chart->removeAxis(chart->axisY());
    }

    QPieSeries *series = new QPieSeries;
    series->setHoleSize(ui->dSpinBoxHoleSize->value());
    series->setPieSize(ui->dSpinBoxPieSize->value());

    int colNo = ui->comboBoxScore->currentIndex() + colNoMath;

    for (int i = 0; i < 5; ++i)
    {
   
        QTreeWidgetItem *item = ui->treeWidget->topLevelItem(i);
        series->append(item->text(0), item->text(colNo).toFloat());
    }

    QPieSlice *slice;

    for (int i = 0; i < 5; ++i)
    {
   
        slice = series->slices().at(i);
        slice->setLabel(slice->label() + QString::asprintf("%.0f人, %.2f%%",
                        slice->value(), slice->percentage()));
        connect(slice, SIGNAL(hovered(bool)),
                this, SLOT(on_SliceHigtLight(bool)));
    }

    series->setLabelsVisible(true);
    chart->setTitle("PieChart --" + ui->comboBoxScore->currentText());
    chart->addSeries(series);
    chart->legend()->setAlignment(Qt::AlignRight);
}

void MainWindow::on_SliceHigtLight(bool show)
{
   
    // 鼠标到饼图扇区,弹出动画
    QPieSlice *slice = (QPieSlice*)sender();
    slice->setExploded(show);
}

void MainWindow::on_dSpinBoxHoleSize_valueChanged(double arg1)
{
   
    QPieSeries* series = (QPieSeries*) ui->cvPieChart->chart()->series().at(0);
    series->setHoleSize(arg1);
}

void MainWindow::on_dSpinBoxPieSize_valueChanged(double arg1)
{
   
    QPieSeries* series = (QPieSeries*) ui->cvPieChart->chart()->series().at(0);
    series->setPieSize(arg1);
}

void MainWindow::on_comboBoxTheme_currentIndexChanged(int index)
{
   
    ui->cvPieChart->chart()->setTheme(QChart::ChartTheme(index));
}

(6)堆叠柱状图

在这里插入图片描述

void MainWindow::initStackedBar()
{
   
    QChart *chart = new QChart;
    chart->setTitle("StackedBar演示");
    chart->setAnimationOptions(QChart::SeriesAnimations);
    ui->cvStackedBar->setChart(chart);
    ui->cvStackedBar->setRenderHint(QPainter::Antialiasing);
}

void MainWindow::buildStackedBar()
{
   
    QChart *chart = ui->cvStackedBar->chart();
    chart->removeAllSeries();

    if(chart->axisX() != nullptr)
    {
   
        chart->removeAxis(chart->axisX());
    }

    if(chart->axisY() != nullptr)
    {
   
        chart->removeAxis(chart->axisY());
    }

    // 数据集
    QBarSet *setMath = new QBarSet(theModel->horizontalHeaderItem(colNoMath)->text());
    QBarSet *setChinese = new QBarSet(theModel->horizontalHeaderItem(colNoChinese)->text());
    QBarSet *setEnglish = new QBarSet(theModel->horizontalHeaderItem(colNoEnglish)->text());

    QStringList categories;

    for (int i = 0; i < theModel->rowCount(); ++i)
    {
   
        categories << theModel->item(i, colNoName)->text();

        setMath->append(theModel->item(i, colNoMath)->text().toFloat());
        setChinese->append(theModel->item(i, colNoChinese)->text().toFloat());
        setEnglish->append(theModel->item(i, colNoEnglish)->text().toFloat());
    }

    QStackedBarSeries *series = new QStackedBarSeries;
    series->append(setMath);
    series->append(setChinese);
    series->append(setEnglish);

    chart->addSeries(series);

    QBarCategoryAxis *axisX = new QBarCategoryAxis;
    axisX->append(categories);
    chart->setAxisX(axisX, series);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0, 300);
    axisY->setTitleText("总分");
    chart->setAxisY(axisY, series);
}

(7)百分比柱状图

在这里插入图片描述

void MainWindow::initPercentBar()
{
   
    QChart *chart = new QChart;
    chart->setTitle("PercentBar演示");
    chart->setAnimationOptions(QChart::SeriesAnimations);
    ui->cvPercentBar->setChart(chart);
    ui->cvPercentBar->setRenderHint(QPainter::Antialiasing);
}

void MainWindow::buildPercentBar()
{
   
    QChart *chart = ui->cvPercentBar->chart();
    chart->removeAllSeries();

    if(chart->axisX() != nullptr)
    {
   
        chart->removeAxis(chart->axisX());
    }

    if(chart->axisY() != nullptr)
    {
   
        chart->removeAxis(chart->axisY());
    }

    // 数据集
    QBarSet *setMath = new QBarSet(theModel->horizontalHeaderItem(colNoMath)->text());
    QBarSet *setChinese = new QBarSet(theModel->horizontalHeaderItem(colNoChinese)->text());
    QBarSet *setEnglish = new QBarSet(theModel->horizontalHeaderItem(colNoEnglish)->text());

    QStringList categories;

    for (int i = 0; i < 5; ++i)
    {
   
        categories << ui->treeWidget->topLevelItem(i)->text(colNoName);

        setMath->append(ui->treeWidget->topLevelItem(i)->text(colNoMath).toFloat());
        setChinese->append(ui->treeWidget->topLevelItem(i)->text(colNoChinese).toFloat());
        setEnglish->append(ui->treeWidget->topLevelItem(i)->text(colNoEnglish).toFloat());
    }

    QPercentBarSeries *series = new QPercentBarSeries;
    series->append(setMath);
    series->append(setChinese);
    series->append(setEnglish);

    chart->addSeries(series);

    QBarCategoryAxis *axisX = new QBarCategoryAxis;
    axisX->append(categories);
    chart->setAxisX(axisX, series);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0, 100);
    axisY->setTitleText("分数百分比");
    chart->setAxisY(axisY, series);
}

(8)散点曲线图

在这里插入图片描述

void MainWindow::initScatterChart()
{
   
    QChart *chart = new QChart;
    chart->setTitle("ScatterChart演示");
    chart->setAnimationOptions(QChart::SeriesAnimations);
    ui->cvScatterChart->setChart(chart);
    ui->cvScatterChart->setRenderHint(QPainter::Antialiasing);
}

void MainWindow::buildScatterChart()
{
   
    QChart *chart = ui->cvScatterChart->chart();
    chart->removeAllSeries();

    if(chart->axisX() != nullptr)
    {
   
        chart->removeAxis(chart->axisX());
    }

    if(chart->axisY() != nullptr)
    {
   
        chart->removeAxis(chart->axisY());
    }

    QSplineSeries *seriesLine = new QSplineSeries;
    seriesLine->setName("spline");

    QPen pen;
    pen.setWidth(2);
    pen.setColor(Qt::red);
    seriesLine->setPen(pen);

    QScatterSeries *series0 = new QScatterSeries;
    series0->setName("散点");
    series0->setMarkerShape(QScatterSeries::MarkerShapeCircle); // 圆形
    series0->setBorderColor(Qt::black);
    series0->setBrush(QBrush(Qt::blue));
    series0->setMarkerSize(12);

    for (int i = 0; i < 10; ++i)
    {
   
        int x = qrand() % 20;
        int y = qrand() % 20;
        series0->append(x, y);
        seriesLine->append(x, y);
    }

    chart->addSeries(seriesLine);
    chart->addSeries(series0);

    chart->createDefaultAxes();
    chart->axisX()->setTitleText("X轴");
    chart->axisX()->setRange(-5, 25);
    chart->axisY()->setTitleText("Y轴");
    chart->axisY()->setRange(-5, 25);
}

四、图表其他操作

图表特定鼠标事件操作需要使用继承类实现事件的处理

1、实现程序

在这里插入图片描述

(1)创建项目,基于QMainWindow

(2)添加资源文件与图标

(3)添加QChartView派生类

#include "axbchartview.h"

AXBChartView::AXBChartView(QWidget *parent) : QChartView(parent)
{
   
    setMouseTracking(true); //
    setDragMode(QGraphicsView::RubberBandDrag); // 框选区域
}

void AXBChartView::keyPressEvent(QKeyEvent *event)
{
   
    switch (event->key())
    {
   
    case Qt::Key_Plus:
    {
   
        chart()->zoom(1.2);
    }
    break;

    case Qt::Key_Minus:
    {
   
        chart()->zoom(0.8);
    }
    break;

    case Qt::Key_Left:
    {
   
        chart()->scroll(10, 0);
    }
    break;

    case Qt::Key_Right:
    {
   
        chart()->scroll(-10, 0);
    }
    break;

    case Qt::Key_Up:
    {
   
        chart()->scroll(0, -10);
    }
    break;

    case Qt::Key_Down:
    {
   
        chart()->scroll(0, 10);
    }
    break;

    case Qt::Key_PageUp:
    {
   
        chart()->scroll(0, -50);
    }
    break;

    case Qt::Key_PageDown:
    {
   
        chart()->scroll(0, 50);
    }
    break;

    case Qt::Key_Home:
    {
   
        chart()->zoomReset();
    }
    break;

    default:
        QGraphicsView::keyPressEvent(event);
        break;
    }
}

void AXBChartView::mousePressEvent(QMouseEvent *event)
{
   
    if(event->button() == Qt::LeftButton)
    {
   
        beginPoint = event->pos();
    }

    QChartView::mousePressEvent(event);
}

void AXBChartView::mouseMoveEvent(QMouseEvent *event)
{
   
    QPoint point = event->pos();
    emit mouseMovePoint(point);
    QChartView::mouseMoveEvent(event);
}

void AXBChartView::mouseReleaseEvent(QMouseEvent *event)
{
   
    if(event->button() == Qt::LeftButton)
    {
   
        endPoint = event->pos();
        QRectF rectF;
        rectF.setTopLeft(beginPoint);
        rectF.setBottomRight(endPoint);
        if(rectF.width() > 10 || rectF.height() > 10)
        {
   
            chart()->zoomIn(rectF);
        }
    }
    else if(event->button() == Qt::RightButton)
    {
   
        chart()->zoomReset();
    }

    QChartView::mouseReleaseEvent(event);
}

(4)实现功能

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "axbchartview.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
   
    ui->setupUi(this);
    setCentralWidget(ui->chartView);

    labXYValue = new QLabel("坐标X: Y: ");
    labXYValue->setMinimumWidth(200);
    ui->statusBar->addWidget(labXYValue);

    createChart();
    prepareData();

    connect(ui->chartView, SIGNAL(mouseMovePoint(QPoint)),
            this, SLOT(on_mouseMovePoint(QPoint)));
}

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

void MainWindow::createChart()
{
   
    QChart *chart = new QChart;
    chart->setTitle("曲线");
    ui->chartView->setChart(chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing);

    QLineSeries *series0 = new QLineSeries;
    QLineSeries *series1 = new QLineSeries;
    series0->setName("Sin曲线");
    series1->setName("Cos曲线");

    QPen pen;
    pen.setStyle(Qt::DotLine);
    pen.setColor(Qt::green);
    pen.setWidth(2);
    series0->setPen(pen);
    pen.setColor(Qt::red);
    series1->setPen(pen);

    chart->addSeries(series0);
    chart->addSeries(series1);
    chart->createDefaultAxes();
    chart->axisX()->setRange(0, 10);
    chart->axisY()->setRange(-1.5, 1.5);

    foreach (auto marker, ui->chartView->chart()->legend()->markers())
    {
   
        connect(marker, SIGNAL(clicked()),
                this, SLOT(on_legendMarkerClicked()));
    }
}

void MainWindow::prepareData()
{
   
    // 准备数据
    QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0);
    QLineSeries *series1 = (QLineSeries *)ui->chartView->chart()->series().at(1);

    qsrand(QTime::currentTime().second());

    for (int i = 0; i < 100; ++i)
    {
   
        qreal dValue;
        dValue = qSin(i * 0.1) + (qrand() % 10 - 5) / 10.0;
        series0->append(i * 0.1, dValue);
        dValue = qCos(i * 0.1) + (qrand() % 10 - 5) / 10.0;
        series1->append(i * 0.1, dValue);
    }
}

void MainWindow::on_mouseMovePoint(QPoint point)
{
   
    QPointF pt = ui->chartView->chart()->mapToValue(point);
    labXYValue->setText(QString::asprintf("坐标X: %.2f Y: %.2f",
                                          pt.x(), pt.y()));
}

void MainWindow::on_legendMarkerClicked()
{
   
    QLegendMarker *marker = (QLegendMarker*)sender();
    marker->series()->setVisible(!marker->series()->isVisible());
    marker->setVisible(true);
    int alpha = 255;

    if(!marker->series()->isVisible())
    {
   
        alpha = 120;
    }

    QBrush brush = marker->labelBrush();
    QColor color = brush.color();
    color.setAlpha(alpha);
    brush.setColor(color);
    marker->setLabelBrush(brush);
}

void MainWindow::on_actZoomIn_triggered()
{
   
    ui->chartView->chart()->zoom(1.2);
}

void MainWindow::on_actZoomOut_triggered()
{
   
    ui->chartView->chart()->zoom(0.8);
}

void MainWindow::on_actZoomReset_triggered()
{
   
    ui->chartView->chart()->zoomReset();
}

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-02-03 07:08:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-03 07:08:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-03 07:08:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-03 07:08:04       18 阅读

热门阅读

  1. uniapp实现自定义底部tab栏

    2024-02-03 07:08:04       30 阅读
  2. QT中的QImage与QPixmap区别

    2024-02-03 07:08:04       29 阅读
  3. webpack详解

    2024-02-03 07:08:04       27 阅读
  4. MySQL数据库安全加固方案

    2024-02-03 07:08:04       26 阅读
  5. Objective-C中里氏替换原则

    2024-02-03 07:08:04       25 阅读
  6. 架构篇31:如何应对接口级的故障?

    2024-02-03 07:08:04       32 阅读