QChart绘制折线图

发布于:2024-08-26 ⋅ 阅读:(110) ⋅ 点赞:(0)

这一篇我们详细介绍图表各个部分的设置和操作,包括图表的标题、图例、边距等属性设置,QLineSeries序列的属性设置,QValueAxis坐标轴的属性设置,以及图标的缩放。(这些应该都是在实际的Qt开发中比较常用的图表操作)先看运行时的界面:

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240824221403.png

界面设计

  • 工具栏:创建几个Action,并创建工具栏,实现图表数据刷新和缩放功能。

  • 主工作区图标视图:从组件面板放置一个QGraphics View组件作为视图组件,并用Promote方法升级为QChartView组件,命名为chartView

  • 图表属性设置面板:左侧是一个QToolBox组件,分为3个操作面板,用于进行图表设置、曲线设置和坐标轴设置。

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240824215739.png

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240824215810.png

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

主窗口类的定义和初始化

下面是主窗口类MainWindow的类定义(省略了Action和界面组件的槽函数定义)。在mainwindow.h文件重需要包含QtChart,并使用宏QT_CHARTS_USE_NAMESPACE导入命名空间。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtCharts>
QT_CHARTS_USE_NAMESPACE
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
private:
    
    QLineSeries* curSeries; // 当前序列
    QValueAxis* curAxis; // 当前坐标轴
    void createChart(); // 创建图表
    void prepareData(); // 更新数据
    void updateFromChart(); // 从图表更新到界面
    
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

MainWindow类中定义了两个私有的变量,curSeries用于指向当前的QLineSeries序列,界面上对序列的设置操作都是针对当前选择的序列;curAxis用于指向当前的QValueAxis坐标轴,对坐标轴进行设置时就是针对当前坐标轴进行设置。

createChart()函数用于创建图表的各个基本部件,在构造函数里调用,prepareData()用于更新序列的数据,updateFormChart()用于读取图表的一些属性,并刷新界面显示。下面是主窗口构造函数,以及这3个函数的代码。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    createChart(); // 创建图表
    prepareData(); // 生成数据
    updateFromChart(); // 从图表获取属性值,刷新到界面显示
}

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();
    curAxis = axisX;
    axisX->setRange(0, 10);
    axisX->setLabelFormat("%.1f"); // 标签格式
    axisX->setTickCount(11); // 主分隔个数
    axisX->setMinorTickCount(9); // 次分隔个数
    axisX->setTitleText("time(secs)"); // 标题

    QValueAxis* axisY = new QValueAxis();
    axisY->setRange(-2, 2);
    axisY->setTitleText("value");
    axisY->setTickCount(5);
    axisY->setLabelFormat("%.2f");
    axisY->setMinorTickCount(4);

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

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

    series0->clear();
    series1->clear();

    qsrand(QTime::currentTime().second()); // 初始化随机数
    qreal t = 0;
    qreal y1, y2;
    qreal intv = 0.1;
    qreal rd;
    int cnt = 100;

    for (int i = 0; i < cnt; i++) {

        rd = (qrand() % 10) - 5;
        y1 = qSin(t) + rd / 50;
        series0->append(t, y1);
        rd = (qrand() % 10) - 5;
        y2 = qCos(t) + rd / 50;
        series1->append(t, y2);
        t += intv;
    }
}

void MainWindow::updateFromChart()
{
    QChart* chart = ui->chartView->chart();
    ui->editTitle->setText(chart->title());
    QMargins mg = chart->margins(); // 边距
    ui->spinMarginTop->setValue(mg.top());
    ui->spinMarginLeft->setValue(mg.left());
    ui->spinMarginRight->setValue(mg.right());
    ui->spinMarginBottom->setValue(mg.bottom());
}
  • MainWindow类个构造函数调用单个私有函数进行图表和界面的初始化。

  • createChart()函数用于创建QChart对象,创建数据序列和坐标轴,并将这些部件组合成一个完整的图表。

  • prepareDate()函数用于为图表重的两个序列生成数据,其中使用随机数,以便使得每次生成的数据稍有不同。

  • updateFromChart()函数用于将图表重的标题和边距信息显示到窗口界面上。

笔画设置对话框QWDialogPen

在这个demo中,需要设置一些对象的pen属性,比如折线序列的pen属性,网络先的pen属性等。pen属性其实就是一个QPen对象,设置内容主要包括线型,线宽和颜色。为了使用方便,设计一个自定义对话框QWDialogPen,专门用于QPen对象的属性设置。

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240825033758.png

QWDialogPen是一个可视化设计的对话框,其类型定义如下:

class QWDialogPen : public QDialog
{
    Q_OBJECT

public:
    explicit QWDialogPen(QWidget *parent = nullptr);
    ~QWDialogPen();
    
    void setPen(QPen pen); // 设置Qpen,用于对话框界面显示
    QPen getPen(); // 获取对话框设置的QPen属性
    static QPen getPen(QPen iniPen, bool& ok); //静态函数
    
private slots:
    void on_btnColor_clicked();
    
private:
    Ui::QWDialogPen *ui;
    QPen m_pen;
};

QWDialogPen类的getPen()以及相关函数的实现代码如下:

void QWDialogPen::setPen(QPen pen)
{
    m_pen = pen;
    ui->spinWidth->setValue(pen.width());
    int i = static_cast<int>(pen.style());
    ui->comboPenStyle->setCurrentIndex(i);
    QColor color = pen.color();
    ui->btnColor->setAutoFillBackground(true);
    QString str = QString::asprintf("background-color: rgb(%d,%d,%d);", color.red(), color.green(), color.blue());
    ui->btnColor->setStyleSheet(str);
}

QPen QWDialogPen::getPen()
{
    m_pen.setStyle(Qt::PenStyle(ui->comboPenStyle->currentIndex()));
    m_pen.setWidth(ui->spinWidth->value());
    QColor color = ui->btnColor->palette().color(QPalette::Button);
    m_pen.setColor(color);
    return m_pen;
}

QPen QWDialogPen::getPen(QPen iniPen, bool &ok)
{
    QWDialogPen* dlg = new QWDialogPen();
    dlg->setPen(iniPen);
    QPen pen;
    int ret = dlg->exec(); // 弹出对话框
    if (ret == QDialog::Accepted) {
        
        pen = dlg->getPen(); // 获取
        ok = true;
    }
    else {
        
        pen = iniPen;
        ok = false;
    }
    
    delete dlg; // 删除对话框对象
    return pen; //返回设置的QPen对象
}

静态函数getPen()里创建了一个QWDialogPen类的实例dlg,然后调用dlg→setPen(iniPen)进行初始化,运行对话框并获取返回值,若返回值为QDialog::Accepted,就调用dlg→getPen()获取设置属性后的QPen对象,最后删除对话框对象并返回设置的Qpen对象。所以,静态函数getPen()就是集成了普通方法调用对话框时创建对话框,设置初始值、获取对话框返回状态、获取返回删除对话框的过程,简化了调用代码。

QChart设置

QChart类的主要函数

分组 函数名 功能描述
图表外观 void setTitle() 设置图表标题,支持HTML
void setTitleFont() 设置图表标题字体
void setTitleBrush() 设置比图表标题画刷
void setTheme() 设置主题,定义了图表的配色
void setMargins() 设置绘图区与图表边界的四个边距
QLegend* legend() 返回图表的图例,是一个QLegend类对象
void setAnimationOptions() 设置序列或坐标轴的动画效果
数据序列 void addSeries() 添加序列
QList<QAbstractSeries*>series() 返回图表拥有的序列的列表
void removeSeries() 移除一个序列,但并不删除序列对象
void removeAllSeries() 移除并删除图表的所有序列
坐标轴 void addAxis() 为图表的某个方向添加坐标轴
QList<QAbstractSeries*> axes() 返回某个方向的坐标轴列表
void setAxisX() 设置某个序列的水平方向的坐标轴
void setAxisY() 设置某个序列的垂直方向的坐标轴
void removeAxis() 移除一个坐标轴
void createDefaultAxes() 更具已添加的序列类型,创建缺省的坐标轴,前面已有的坐标轴会被删除

通过图表的设置界面可以设置标题的内容和字体,可以设置图例的位置,是否显示,字体颜色和边距;可以设置动画效果和主题。

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240825194552.png

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240825194609.png

setAnimationOptions(AnimationOptions options)函数设置图表的动画效果,输入参数是QChart::AnimationOption枚举类型,有以下取值:

  • QChart::NoAnimation:无动画效果;

  • QChart::GridAxisAnimations:背景网格有动画;

  • QChart::SeriesAnimations:序列有动画效果;

  • QChart::AllAnimations:都有动画效果。

主题是预定义的图表配色样式,是QChart::ChartTheme枚举类型,有多种取值。

图例是一个QLegend类对象,通过QChart::legend()可以获取图表的图例。图例是根据添加的序列自动生成的,但是可以修改一些属性,如:位置,文字和字体等。例如:

ui->chartView->chart()->legend()->setAlignment(Qt::AlignBottom);

void MainWindows::on_btnLegendFont_clicked() {

    QFont font = ui->chartView->chart()->legend()->font();
    bool ok = false;
    font = QFontDialog::getFont(&ok, font);
    if (ok) {
      ui->chartView->chart()->legend()->setFont(font);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到