天天看點

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. 在右鍵添加多按鈕,實作圖表的恢複及輸出。

繼續閱讀