1. 程式人生 > >QT5.5.1+QwtPlot繪製二維座標圖

QT5.5.1+QwtPlot繪製二維座標圖

前言:要求必須配置有QwtPlot,否則提供的程式碼無法正常執行。

1.基於QwtPlot編寫新的函式類PlotLines,程式碼如下:

h檔案

#ifndef PLOTLINES_H
#define PLOTLINES_H
#include<qwt_plot.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_renderer.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_histogram.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_zoomer.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_magnifier.h>
#include <qwt_legend.h>
#include <qwt_legend_label.h>
#include <qwt_column_symbol.h>
#include <qwt_series_data.h>
#include <qpen.h>
#include <qwt_symbol.h>
#include <qwt_picker_machine.h>
#include<vector>

using namespace  std;


class PlotLines : public QwtPlot
{
    Q_OBJECT
public:
    explicit PlotLines(QWidget *parent = 0);
    void fucSetLineMsg(int num,vector<QPolygonF> lineData,vector<QString> lineName);
    void fucUpdate();
    void fucSetTitle(QString in) {this->setTitle(in);}
    void fucSetSize(int width,int height) {this->resize(width,height);}
private Q_SLOTS:
    //點選圖例,顯示相應的曲線
    void showItem(const QVariant &itemInfo, bool on);
private:
    void fucInit();
    void fucInitVec();
    int gloLineNum;
    vector<QPolygonF> gloLineData;
    vector<QwtPlotCurve *> gloLine;
    vector<QString> gloLineName;
    vector<QColor> gloColor;
    QwtLegend *legend;
};

#endif // PLOTLINES_H

cpp檔案

#pragma execution_character_set("utf-8")
#include "plotlines.h"

PlotLines::PlotLines(QWidget *parent) :
    QwtPlot(parent)
{
    legend = new QwtLegend;
    fucInitVec();
    fucInit();
    fucUpdate();
}
//點選圖例,顯示相應的曲線
void PlotLines::showItem(const QVariant &itemInfo, bool on)
{
    QwtPlotItem *plotItem = infoToItem( itemInfo );
    if ( plotItem )
        plotItem->setVisible( on );
}
void PlotLines::fucSetLineMsg(int num,vector<QPolygonF> lineData,vector<QString> lineName)
{
    foreach (QwtPlotCurve *i, gloLine)
    {
        i->detach();
    }
    gloLineNum=int(lineData.size());
    gloLineData=lineData;gloLine.clear();gloLineName=lineName;
    int flagTemp=gloLineName.empty();
    if(gloLine.empty() || gloLine.size()!=gloLineNum)
    {
        gloLine.clear();
    for(int i=0;i<gloLineNum;++i)
    {
        QString nameTemp="曲線"+QString::number(i+1);
        if(!flagTemp) nameTemp=gloLineName[i];
        QwtPlotCurve *curve=new QwtPlotCurve(nameTemp);
        curve->setPen(gloColor[i%7],2);//設定曲線顏色 粗細
        curve->setRenderHint(QwtPlotItem::RenderAntialiased,true);//線條光滑化
        QwtSymbol *symbol = new QwtSymbol( QwtSymbol::Ellipse,
                                           QBrush( Qt::black ), QPen( gloColor[i%7], 2 ), QSize( 6, 6) );//設定樣本點的顏色、大小
        curve->setSymbol( symbol );//新增樣本點形狀
        curve->setSamples(gloLineData[i]);
        curve->attach( this );
        curve->setLegendAttribute(curve->LegendShowLine);
        gloLine.push_back(curve);
    }
    }
    else
    {
        for(int i=0;i<gloLineNum;++i)
        {
            QwtPlotCurve *temp=gloLine[i];
            temp->setSamples(gloLineData[i]);
        }
    }
}
void PlotLines::fucUpdate()
{
    this->replot();
    setAutoReplot();
    //獲取畫了多少條曲線,如果為獲取其他形狀,注意改變引數
    QwtPlotItemList items = itemList( QwtPlotItem::Rtti_PlotCurve );
    for ( int i = 0; i < items.size(); i++ )
    {


        {
            const QVariant itemInfo = itemToInfo( items[i] );
            QwtLegendLabel *legendLabel =
                    qobject_cast<QwtLegendLabel *>( legend->legendWidget( itemInfo ) );
            if ( legendLabel )
                legendLabel->setChecked( true );//
        }
    }

}
void PlotLines::fucInit()
{
    //---------設定畫布---------//
    QwtPlotCanvas *canvas=new QwtPlotCanvas();
    canvas->setPalette(Qt::white);
    canvas->setBorderRadius(10);
    setCanvas( canvas );
    plotLayout()->setAlignCanvasToScales( true );

    //-----------設定x,y座標和範圍--------------//
    setAxisTitle( QwtPlot::yLeft, "y軸" );
    setAxisTitle( QwtPlot::xBottom, "x軸" );
    //----------------設定柵格線-------------------//
    QwtPlotGrid *grid = new QwtPlotGrid;
    grid->enableX( true );//設定網格線
    grid->enableY( true );
    grid->setMajorPen( Qt::black, 0, Qt::DotLine );
    grid->attach( this );
    //--------------設定圖例可以被點選來確定是否顯示曲線-----------------------//

    legend->setDefaultItemMode( QwtLegendData::Checkable );//圖例可被點選
    insertLegend( legend, QwtPlot::RightLegend );
    connect( legend, SIGNAL( checked( const QVariant &, bool, int ) ),
             SLOT( showItem( const QVariant &, bool ) ) );//點選圖例操作

    QwtPlotItemList items = itemList( QwtPlotItem::Rtti_PlotCurve );//獲取畫了多少條曲線,如果為獲取其他形狀,注意改變引數
    //  qDebug()<<items;
    for ( int i = 0; i < items.size(); i++ )
    {

        if ( i == 0 )
        {
            const QVariant itemInfo = itemToInfo( items[i] );

            QwtLegendLabel *legendLabel =
                    qobject_cast<QwtLegendLabel *>( legend->legendWidget( itemInfo ) );
            if ( legendLabel )
                legendLabel->setChecked( true );//

            items[i]->setVisible( true );
        }
        else
        {
            items[i]->setVisible( false );
        }
    }

}
void PlotLines::fucInitVec()
{
    gloColor.push_back(QColor(255,0,0));
    gloColor.push_back(QColor(255,128,0));
    gloColor.push_back(QColor(255,255,0));
    gloColor.push_back(QColor(0,255,0));
    gloColor.push_back(QColor(0,0,255));
    gloColor.push_back(QColor(0,255,255));
    gloColor.push_back(QColor(128,0,255));
}

2.PlotLines是基於QwtPlot生成的新的方法類,其公共函式介面作用如下:

(1)PlotLines(QWidget *parent = 0);建構函式,父控制元件可為空,也可為具體介面;

(2)fucSetTitle設定顯示出的座標圖的名稱;

(3)fucSetSize設定座標圖的長寬尺寸(移動顯示位置可以使用基於QwtPlot的move函式);

(4)fucSetLineMsg(int num,vector<QPolygonF> lineData,vector<QString> lineName);num為設定的折線的數目;lineData就是需要顯示的座標點的集合(存在num與lineData數目不和的情況,因此使用的是lineData數目,num實際不起作用,筆者較懶,未改動),lineName為各個曲線的名稱(可為空,此時曲線以“曲線1”之類以此類推命名,但是如果不為空,linename數目必不能少於lineName的數目,此處也可在程式碼中修改,留給讀者自行掌握)。QPolygonF的寫入座標方法:

QPolygonF in;
in<<QPoint(1,qrand()%100);

(5)fucUpdate();曲線重畫方法,呼叫(4)函式更新資料點後,必須呼叫該方法才能重新整理介面顯示。

3,最終的使用效果如下

通過點選圖示,可以進行折線的顯示與隱藏。

注意:

(1)筆者只設定了七種顏色的線條顏色,當涉及到7以上的線條時,重複這七種顏色;

(2)動態畫圖也很簡單,寫一個定時器,更新lineData資料,呼叫fucSetLineMsg()及fucUpdate兩個方法即可。