天天看点

QCustomplot的基本使用方法

QCustomplot的基本使用方法

    • 一、准备工作
    • 二、使用方法
      • 头文件内容
      • cpp文件内容
    • 三、总结

最近在写一个程序需要画图,原本使用的是qtcharts,但是有可能是我使用方法没对,用qtcharts画图的效率极其低下,上万个点时,尤其是可能卡死,后来听说qcustomplot好用,于是改用qcustomplot,果不其然,一万多个点,几乎秒出。

qcustomplot的使用方法与qtchart不太相同,因此记录一二。

我所使用的qcustomplot版本为2.0版本。

一、准备工作

qcustomplot使用过程中,有如下几个注意点:

  1. 有几种使用方法,我采用的是,将qcustomplot.h与qcustomplot.cpp放置工程文件下,而后导入;
  2. 修改pro文件,添加两个内容,一个是

    QT += printsupport

    ,另一个是

    DEFINES += QCUSTOMPLOT_USE_OPENGL

    ,前者的作用是为了使用该控件,后者的作用是为了让画图过程中使用OpenGL以增加效率,另外,如果你是后来添加的

    DEFINES += QCUSTOMPLOT_USE_OPENGL

    则需要清除工程文件,重新构建,因为这部分内容需要写入预编译产生的文件中;
  3. 在ui文件中,添加一个Widget的控件,提升为qcustomplot,这个需要自己手动将刚刚导入进来的qcustomplot添加到提升的类中。

二、使用方法

该部分内容,直接贴代码,看注释。这是一个在dialog中通过提升Wdiget实现qcustomplot的方法。

头文件内容

#include <QDialog>

namespace Ui {
class precisionPaintDialog;
}
class precisionPaintDialog : public QDialog
{
    Q_OBJECT

public:
    explicit precisionPaintDialog(QWidget *parent = 0);
    ~precisionPaintDialog();
    
    void addGraphs();  
    QVector<double> x1;  //图表1的X轴数据
    QVector<double> c1;  //图表1的Y轴数据
    QVector<double> x2;  //图表2的X轴数据
    QVector<double> c2;  //图表2的X轴数据

public slots:
    //图表1的鼠标右键功能
    void mouseReleaseEvent_plot1(QMouseEvent * event); 
    //图表2的鼠标右键功能
    void mouseReleaseEvent_plot2(QMouseEvent * event);

private:
    Ui::precisionPaintDialog *ui;
private slots:
        void recover_btn_plot1(); //图表1的恢复功能
        void recover_btn_plot2(); //图表2的恢复功能
        void save_jpg_btn_plot1();  //图表1的保存为jpg功能
        void save_jpg_btn_plot2();  //图表2的保存为jpg功能
};
           

cpp文件内容

#include "precisionpaintdialog.h"
#include "ui_precisionpaintdialog.h"

precisionPaintDialog::precisionPaintDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::precisionPaintDialog)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::WindowMinMaxButtonsHint);
    //图方便,我就用10000个相同的值的点来演示,反正数值大小无所谓。
    for(int i = 0 ; i<10000;i++){
            x1.append(i);
            c1.append(0.01);
            
            x2.append(i);
            c2.append(0.02);
    }
    //将第一个widget控件的鼠标释放的信号与自己定义个一个函数相连接,为了方便使用,我自行定义了一个函数。
    connect(ui->widget_plot,SIGNAL(mouseRelease(QMouseEvent*)),this,SLOT(mouseReleaseEvent_plot1(QMouseEvent*)));
    //将第二个widget控件的鼠标释放的信号与自己定义个一个函数相连接,为了方便使用,我自行定义了一个函数。
    connect(ui->widget_plot_2,SIGNAL(mouseRelease(QMouseEvent*)),this,SLOT(mouseReleaseEvent_plot2(QMouseEvent*)));
    
    //实现添加图表及图表的配置,及图表的数据的函数。
    addGraphs();
}

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

//图表的初始化函数
void precisionPaintDialog::addGraphs()
{
	//这个是坐标轴的固有属性的一个策略类,利用该策略,可以实现指定坐标轴的一些属性,比如刻度步长,刻度数目等等。
    QSharedPointer<QCPAxisTickerFixed> ticker(new QCPAxisTickerFixed);
    //设置刻度步长为0.004
    ticker.data()->setTickStep(0.004);
    //设置坐标轴有9个刻度值
    ticker.data()->setTickCount(9);
	
	//新增一个图表
    ui->widget_plot->addGraph();
    //设置图表的名称
    ui->widget_plot->graph()->setName("通道A随机误差");
    //将横轴和纵轴的值赋值给坐标轴
    ui->widget_plot->graph()->setData(x1, c1);
    //设置X轴的标签
    ui->widget_plot->xAxis->setLabel("相对时(秒)");
    //设置Y轴的标签
    ui->widget_plot->yAxis->setLabel("通道A随机误差");
    //设置X轴的值的范围
    ui->widget_plot->xAxis->setRange(x1.first(),x1.last());
    //设置Y轴的值的范围
    ui->widget_plot->yAxis->setRange(0,0.032);
    //将刚生成的坐标轴的策略,设置到Y轴上
    ui->widget_plot->yAxis->setTicker(ticker);
    //设置该坐标轴可拖动,可缩放
    ui->widget_plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
    //设置使用opengl画图
    ui->widget_plot->setOpenGl(true);
    //画图
    ui->widget_plot->replot();

	//图表2与图表1一模一样,不赘述
    ui->widget_plot_2->addGraph();
    ui->widget_plot_2->yAxis->ticker().data()->setTickCount(9);
    ui->widget_plot_2->graph()->setName("通道B随机误差");
    ui->widget_plot_2->graph()->setData(x2, c2);
    ui->widget_plot_2->xAxis->setLabel("相对时(秒)");
    ui->widget_plot_2->yAxis->setLabel("通道B随机误差");
    ui->widget_plot_2->xAxis->setRange(x2.first(),x2.last());
    ui->widget_plot_2->yAxis->setRange(0,0.032);
    ui->widget_plot_2->yAxis->setTicker(ticker);
    ui->widget_plot_2->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
    ui->widget_plot_2->setOpenGl(true);
    ui->widget_plot_2->replot();

}

//右键时显示右键菜单栏,并实现按钮功能
void precisionPaintDialog::mouseReleaseEvent_plot1(QMouseEvent *event)
{
    if(event->button()==Qt::RightButton)
    {
    	//新建一个菜单
        QMenu *pMenu=new QMenu(ui->widget_plot);
        //新建菜单中的按钮
        QAction *act_Reset=new QAction(tr("复位"),ui->widget_plot);
        QAction *act_Save_jpg=new QAction(tr("保存为jpg"),ui->widget_plot);
        //将按钮添加到菜单
        pMenu->addAction(act_Reset);
        pMenu->addAction(act_Save_jpg);
        //将按钮与实现的功能函数相绑定
        connect(act_Reset,SIGNAL(triggered(bool)),this,SLOT(recover_btn_plot1()));
        connect(act_Save_jpg,SIGNAL(triggered(bool)),this,SLOT(save_jpg_btn_plot1()));
        //在右键点击的位置显示菜单
        pMenu->exec(cursor().pos());
        //释放内存
        QList<QAction*>list=pMenu->actions();
        foreach (QAction* pAction, list) {
            delete pAction;
        }
        delete pMenu;
    }

}
//与上述一致
void precisionPaintDialog::mouseReleaseEvent_plot2(QMouseEvent *event)
{
    if(event->button()==Qt::RightButton)
    {
        QMenu *pMenu=new QMenu(ui->widget_plot_2);

        QAction *act_Reset=new QAction(tr("复位"),ui->widget_plot_2);
        QAction *act_Save_jpg=new QAction(tr("保存为jpg"),ui->widget_plot_2);

        pMenu->addAction(act_Reset);
        pMenu->addAction(act_Save_jpg);

        connect(act_Reset,SIGNAL(triggered(bool)),this,SLOT(recover_btn_plot2()));
        connect(act_Save_jpg,SIGNAL(triggered(bool)),this,SLOT(save_jpg_btn_plot2()));
        
        pMenu->exec(cursor().pos());
        QList<QAction*>list=pMenu->actions();
        foreach (QAction* pAction, list) {
            delete pAction;
        }
        delete pMenu;
    }

}

//实现恢复图表初始化界面的功能
void precisionPaintDialog::recover_btn_plot1()
{
    ui->widget_plot->xAxis->setRange(x1.first(),x1.last());
    ui->widget_plot->yAxis->setRange(0,0.032);
    ui->widget_plot->replot();
}

//实现保存为图输出的功能
void precisionPaintDialog::save_jpg_btn_plot1()
{
	//保存的位置,如果不存在,则创建文件夹
    QString path=QCoreApplication::applicationDirPath()+"/SavePicture/precision";
    QDir dir(path);
    if(!dir.exists()){
        dir.mkpath(path);
    }
    QString pathA = path +"/channelA_"+QTime::currentTime().toString().replace(":","")+".jpg";
    //保存为jps输出,也可以保存为bmp,pdf,png等格式输出,相应的函数分别为saveBmp,savePdf,savePng。
    if(ui->widget_plot->saveJpg(pathA)){
        int click=QMessageBox::warning(this,"提示","图片已保存!是否打开保存目录?",QMessageBox::Yes,QMessageBox::No);
        //打开图片所在目录的文件夹
        if(click==QMessageBox::Yes){
            QDesktopServices::openUrl(QUrl::fromLocalFile(path));
        }
    }else{
        QMessageBox::information(this,"提示","图片保存失败!");
    }
}

//同上类似
void precisionPaintDialog::recover_btn_plot2()
{
    ui->widget_plot_2->xAxis->setRange(x2.first(),x2.last());
    ui->widget_plot_2->yAxis->setRange(0,0.032);
    ui->widget_plot_2->replot();
}
//同上类似
void precisionPaintDialog::save_jpg_btn_plot2()
{
    QString path=QCoreApplication::applicationDirPath()+"/SavePicture/precision";
    QDir dir(path);
    if(!dir.exists()){
        dir.mkpath(path);
    }
    QString pathB = path +"/channelB_"+QTime::currentTime().toString().replace(":","")+".jpg";
    if(ui->widget_plot->saveJpg(pathB)){
        int click=QMessageBox::warning(this,"提示","图片已保存!是否打开保存目录?",QMessageBox::Yes,QMessageBox::No);
        if(click==QMessageBox::Yes){
            QDesktopServices::openUrl(QUrl::fromLocalFile(path));
        }
    }else{
        QMessageBox::information(this,"提示","图片保存失败!");
    }
}

           

三、总结

实现了如下功能:

  1. 实现在一个dialog中使用多个qcustomplot提升的widget控件;
  2. 实现指定坐标轴的刻度的步长;
  3. 实现图表的缩放,平移;
  4. 在右键添加多按钮,实现图表的恢复及输出。

继续阅读