QWT基础教程之legends

效果预览

工程目录树如下

.
|
|---Headers
|     |---mainwindow.h
|     |---panel.h
|     |---plot.h
|     |---settings.h
|
|---Sources
|     |---main.cpp
|     |---mainwindow.cpp
|     |---panel.cpp
|     |---plot.cpp

这里一共有4个.h文件,4个.c文件,涉及到4个主要类:MainWindow、Panel、Plot、Settings。下面逐个浏览这些类

MainWindow类

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow( QWidget *parent = 0 );

private Q_SLOTS:
    void updatePlot();
    void exportPlot();

private:
    Plot *d_plot;
    Panel *d_panel;
};

MainWindow继承自QMainWindow,两个槽函数,两个私有属性。

构造函数MainWindow实现

MainWindow::MainWindow( QWidget *parent ): QMainWindow( parent )
{
    d_plot = new Plot();
    //新建一个Plot

    Settings settings;
    //新建一个Settings,用来存储配置信息
    settings.legend.isEnabled = true;
    //使能图例
    settings.legend.position = QwtPlot::BottomLegend;
    //图例位置

    settings.legendItem.isEnabled = false;
    //失能图例Item
    settings.legendItem.numColumns = 1;
    //设置图例Item列数
    settings.legendItem.alignment = Qt::AlignRight | Qt::AlignVCenter;
    //设置图例Item对齐方式
    settings.legendItem.backgroundMode = 0;
    //设置图例Item背景模式
    settings.legendItem.size = d_plot->canvas()->font().pointSize();
    //设置图例Item尺寸
    
    //这里来区分一下legend和legendItem,前者是plot自带的图例,后者是一个专门的图例类。

    settings.curve.numCurves = 4;
    //设置曲线数量
    settings.curve.title = "Curve";
    //设置曲线名称

    d_panel = new Panel();
    //新建控制面板
    d_panel->setSettings( settings );
    //用之前初始化号的settings来初始化面板

    QWidget *box = new QWidget( this );
    //新建一个Widget
    QHBoxLayout *layout = new QHBoxLayout( box );
    //新建一个水平布局,父对象为box
    layout->addWidget( d_plot, 10 );
    //向布局中添加plot
    layout->addWidget( d_panel );
    //向布局中添加panel

    setCentralWidget( box );
    //将包含水平布局的box设置为MainWindow的核心控件

    QToolBar *toolBar = new QToolBar( this );
    //新建一个工具栏

    QToolButton *btnExport = new QToolButton( toolBar );
    //以工具栏为父对象新建一个工具按钮
    btnExport->setText( "Export" );
    //为工具按钮设置文字标识
    toolBar->addWidget( btnExport );
    //将工具按钮添加到工具栏

    addToolBar( toolBar );
    //将工具栏添加到MainWindow

    updatePlot();
    //更新画板

    connect( d_panel, SIGNAL( edited() ), SLOT( updatePlot() ) );
    connect( btnExport, SIGNAL( clicked() ), SLOT( exportPlot() ) );
    //两个槽函数,一个用来检查面板参数是否发生变动,一个用来将图像导出
}

下面是两个槽函数

void MainWindow::updatePlot()
{
    d_plot->applySettings( d_panel->settings() );
}
//一个槽函数,当面板上的信息发生改变时,面板对象会发出一个edited信号,MainWindow会接收到

void MainWindow::exportPlot()
{
    QwtPlotRenderer renderer;
    renderer.exportTo( d_plot, "legends.pdf" );
}
//一个槽函数,绑定在一个按钮上,用来将图像导出

Panel类

#include "settings.h"
#include <qwidget.h>

class QCheckBox;
class QComboBox;
class QSpinBox;
class QLineEdit;

class Panel: public QWidget
{
    Q_OBJECT

public:
    Panel( QWidget *parent = NULL );

    void setSettings( const Settings &);
    Settings settings() const;

Q_SIGNALS:
    void edited();

private:
    struct
    {
        QCheckBox *checkBox;
        QComboBox *positionBox;

    } d_legend;

    struct
    {
        QCheckBox *checkBox;
        QSpinBox *numColumnsBox;
        QComboBox *hAlignmentBox;
        QComboBox *vAlignmentBox;
        QComboBox *backgroundBox;
        QSpinBox *sizeBox;

    } d_legendItem;

    struct
    {
        QSpinBox *numCurves;
        QLineEdit *title;

    } d_curve;
};

构造函数Panel实现

Panel::Panel( QWidget *parent ):
    QWidget( parent )
{
    // create widgets

    d_legend.checkBox = new QCheckBox( "Enabled" );

    d_legend.positionBox = new QComboBox();
    d_legend.positionBox->addItem( "Left", QwtPlot::LeftLegend );
    d_legend.positionBox->addItem( "Right", QwtPlot::RightLegend );
    d_legend.positionBox->addItem( "Bottom", QwtPlot::BottomLegend );
    d_legend.positionBox->addItem( "Top", QwtPlot::TopLegend );
    d_legend.positionBox->addItem( "External", QwtPlot::TopLegend + 1 );

    d_legendItem.checkBox = new QCheckBox( "Enabled" );

    d_legendItem.numColumnsBox = new QSpinBox();
    d_legendItem.numColumnsBox->setRange( 0, 10 );
    d_legendItem.numColumnsBox->setSpecialValueText( "Unlimited" );

    d_legendItem.hAlignmentBox = new QComboBox();
    d_legendItem.hAlignmentBox->addItem( "Left", Qt::AlignLeft );
    d_legendItem.hAlignmentBox->addItem( "Centered", Qt::AlignHCenter );
    d_legendItem.hAlignmentBox->addItem( "Right", Qt::AlignRight );

    d_legendItem.vAlignmentBox = new QComboBox();
    d_legendItem.vAlignmentBox->addItem( "Top", Qt::AlignTop );
    d_legendItem.vAlignmentBox->addItem( "Centered", Qt::AlignVCenter );
    d_legendItem.vAlignmentBox->addItem( "Bottom", Qt::AlignBottom );

    d_legendItem.backgroundBox = new QComboBox();
    d_legendItem.backgroundBox->addItem( "Legend",
        QwtPlotLegendItem::LegendBackground );
    d_legendItem.backgroundBox->addItem( "Items",
        QwtPlotLegendItem::ItemBackground );

    d_legendItem.sizeBox = new QSpinBox();
    d_legendItem.sizeBox->setRange( 8, 22 );

    d_curve.numCurves = new QSpinBox();
    d_curve.numCurves->setRange( 0, 99 );

    d_curve.title = new QLineEdit();

    // layout

    QGroupBox *legendBox = new QGroupBox( "Legend" );
    QGridLayout *legendBoxLayout = new QGridLayout( legendBox );

    int row = 0;
    legendBoxLayout->addWidget( d_legend.checkBox, row, 0, 1, -1 );

    row++;
    legendBoxLayout->addWidget( new QLabel( "Position" ), row, 0 );
    legendBoxLayout->addWidget( d_legend.positionBox, row, 1 );


    QGroupBox *legendItemBox = new QGroupBox( "Legend Item" );
    QGridLayout *legendItemBoxLayout = new QGridLayout( legendItemBox );

    row = 0;
    legendItemBoxLayout->addWidget( d_legendItem.checkBox, row, 0, 1, -1 );

    row++;
    legendItemBoxLayout->addWidget( new QLabel( "Columns" ), row, 0 );
    legendItemBoxLayout->addWidget( d_legendItem.numColumnsBox, row, 1 );

    row++;
    legendItemBoxLayout->addWidget( new QLabel( "Horizontal" ), row, 0 );
    legendItemBoxLayout->addWidget( d_legendItem.hAlignmentBox, row, 1 );

    row++;
    legendItemBoxLayout->addWidget( new QLabel( "Vertical" ), row, 0 );
    legendItemBoxLayout->addWidget( d_legendItem.vAlignmentBox, row, 1 );

    row++;
    legendItemBoxLayout->addWidget( new QLabel( "Background" ), row, 0 );
    legendItemBoxLayout->addWidget( d_legendItem.backgroundBox, row, 1 );

    row++;
    legendItemBoxLayout->addWidget( new QLabel( "Size" ), row, 0 );
    legendItemBoxLayout->addWidget( d_legendItem.sizeBox, row, 1 );

    QGroupBox *curveBox = new QGroupBox( "Curves" );
    QGridLayout *curveBoxLayout = new QGridLayout( curveBox );

    row = 0;
    curveBoxLayout->addWidget( new QLabel( "Number" ), row, 0 );
    curveBoxLayout->addWidget( d_curve.numCurves, row, 1 );

    row++;
    curveBoxLayout->addWidget( new QLabel( "Title" ), row, 0 );
    curveBoxLayout->addWidget( d_curve.title, row, 1 );

    QVBoxLayout *layout = new QVBoxLayout( this );
    layout->addWidget( legendBox );
    layout->addWidget( legendItemBox );
    layout->addWidget( curveBox );
    layout->addStretch( 10 );

    connect( d_legend.checkBox,
        SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
    connect( d_legend.positionBox,
        SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );

    connect( d_legendItem.checkBox,
        SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
    connect( d_legendItem.numColumnsBox,
        SIGNAL( valueChanged( int ) ), SIGNAL( edited() ) );
    connect( d_legendItem.hAlignmentBox,
        SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
    connect( d_legendItem.vAlignmentBox,
        SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
    connect( d_legendItem.backgroundBox,
        SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
    connect( d_curve.numCurves,
        SIGNAL( valueChanged( int ) ), SIGNAL( edited() ) );
    connect( d_legendItem.sizeBox,
        SIGNAL( valueChanged( int ) ), SIGNAL( edited() ) );
    connect( d_curve.title,
        SIGNAL( textEdited( const QString & ) ), SIGNAL( edited() ) );
}

重点理解QT中的信号到信号的连接,进一步熟悉QT中布局类的使用

setSettings实现,用于设置控制面板

void Panel::setSettings( const Settings &settings)
{
    blockSignals( true );

    d_legend.checkBox->setCheckState(
        settings.legend.isEnabled ? Qt::Checked : Qt::Unchecked );
    d_legend.positionBox->setCurrentIndex( settings.legend.position );

    d_legendItem.checkBox->setCheckState(
        settings.legendItem.isEnabled ? Qt::Checked : Qt::Unchecked );

    d_legendItem.numColumnsBox->setValue( settings.legendItem.numColumns );

    int align = settings.legendItem.alignment;

    if ( align & Qt::AlignLeft )
        d_legendItem.hAlignmentBox->setCurrentIndex( 0 );
    else if ( align & Qt::AlignRight )
        d_legendItem.hAlignmentBox->setCurrentIndex( 2 );
    else
        d_legendItem.hAlignmentBox->setCurrentIndex( 1 );

    if ( align & Qt::AlignTop )
        d_legendItem.vAlignmentBox->setCurrentIndex( 0 );
    else if ( align & Qt::AlignBottom )
        d_legendItem.vAlignmentBox->setCurrentIndex( 2 );
    else
        d_legendItem.vAlignmentBox->setCurrentIndex( 1 );

    d_legendItem.backgroundBox->setCurrentIndex(
        settings.legendItem.backgroundMode );

    d_legendItem.sizeBox->setValue( settings.legendItem.size );

    d_curve.numCurves->setValue( settings.curve.numCurves );
    d_curve.title->setText( settings.curve.title );

    blockSignals( false );
}

settings实现,用于获取当前控制面板的设置信息

Settings Panel::settings() const
{
    Settings s;

    s.legend.isEnabled =
        d_legend.checkBox->checkState() == Qt::Checked;
    s.legend.position = d_legend.positionBox->currentIndex();

    s.legendItem.isEnabled =
        d_legendItem.checkBox->checkState() == Qt::Checked;
    s.legendItem.numColumns = d_legendItem.numColumnsBox->value();

    int align = 0;

    int hIndex = d_legendItem.hAlignmentBox->currentIndex();
    if ( hIndex == 0 )
        align |= Qt::AlignLeft;
    else if ( hIndex == 2 )
        align |= Qt::AlignRight;
    else
        align |= Qt::AlignHCenter;

    int vIndex = d_legendItem.vAlignmentBox->currentIndex();
    if ( vIndex == 0 )
        align |= Qt::AlignTop;
    else if ( vIndex == 2 )
        align |= Qt::AlignBottom;
    else
        align |= Qt::AlignVCenter;

    s.legendItem.alignment = align;

    s.legendItem.backgroundMode =
            d_legendItem.backgroundBox->currentIndex();
    s.legendItem.size = d_legendItem.sizeBox->value();

    s.curve.numCurves = d_curve.numCurves->value();
    s.curve.title = d_curve.title->text();

    return s;
}

Plot类,继承自QwtPlot,一个画板类

#include <qwt_plot.h>

class Settings;
class LegendItem;
class QwtLegend;

class Plot: public QwtPlot
{
    Q_OBJECT

public:
    Plot( QWidget *parent = NULL );
    virtual ~Plot();

public Q_SLOTS:
    void applySettings( const Settings & );

public:
    virtual void replot();

private:
    void insertCurve();

    QwtLegend *d_externalLegend;
    LegendItem *d_legendItem;
    bool d_isDirty;
};

构造函数Plot

Plot::Plot( QWidget *parent ):
    QwtPlot( parent ),
    d_externalLegend( NULL ),
    d_legendItem( NULL ),
    d_isDirty( false )
{
    QwtPlotCanvas *canvas = new QwtPlotCanvas();
    //新建一张画布
    canvas->setFocusIndicator( QwtPlotCanvas::CanvasFocusIndicator );
    canvas->setFocusPolicy( Qt::StrongFocus );
    canvas->setPalette( Qt::black );
    //设置一些画布属性,感兴趣的可以去查文档,或者上网看看别人的理解
    setCanvas( canvas );
    //为画板设置画布

    setAutoReplot( false );
    //禁止自动重绘

    setTitle( "Legend Test" );
    setFooter( "Footer" );

    // grid
    QwtPlotGrid *grid = new QwtPlotGrid;
    grid->enableXMin( true );
    grid->setMajorPen( Qt::gray, 0, Qt::DotLine );
    grid->setMinorPen( Qt::darkGray, 0, Qt::DotLine );
    grid->attach( this );

    // axis
    setAxisScale( QwtPlot::yLeft, 0.0, 1000.0 );
    setAxisScale( QwtPlot::xBottom, 0.0, 1000.0 );
}

applySettings实现,被外部调用,用于在画板上绘制曲线

void Plot::applySettings( const Settings &settings )
{
    d_isDirty = false;
    setAutoReplot( true );

    if ( settings.legend.isEnabled )
    {
        if ( settings.legend.position > QwtPlot::TopLegend )
        {
            if ( legend() )
            {
                // remove legend controlled by the plot
                insertLegend( NULL );
            }

            if ( d_externalLegend == NULL )
            {
                d_externalLegend = new QwtLegend();
                d_externalLegend->setWindowTitle("Plot Legend");

                connect(
                    this,
                    SIGNAL( legendDataChanged( const QVariant &,
                        const QList<QwtLegendData> & ) ),
                    d_externalLegend,
                    SLOT( updateLegend( const QVariant &,
                        const QList<QwtLegendData> & ) ) );

                d_externalLegend->show();

                // populate the new legend
                updateLegend();
            }
        }
        else
        {
            delete d_externalLegend;
            d_externalLegend = NULL;

            if ( legend() == NULL ||
                plotLayout()->legendPosition() != settings.legend.position )
            {
                insertLegend( new QwtLegend(),
                    QwtPlot::LegendPosition( settings.legend.position ) );
            }
        }
    }
    else
    {
        insertLegend( NULL );

        delete d_externalLegend;
        d_externalLegend = NULL;
    }

    if ( settings.legendItem.isEnabled )
    {
        if ( d_legendItem == NULL )
        {
            d_legendItem = new LegendItem();
            d_legendItem->attach( this );
        }

        d_legendItem->setMaxColumns( settings.legendItem.numColumns );
        d_legendItem->setAlignment( Qt::Alignment( settings.legendItem.alignment ) );
        d_legendItem->setBackgroundMode(
            QwtPlotLegendItem::BackgroundMode( settings.legendItem.backgroundMode ) );
        if ( settings.legendItem.backgroundMode ==
            QwtPlotLegendItem::ItemBackground )
        {
            d_legendItem->setBorderRadius( 4 );
            d_legendItem->setMargin( 0 );
            d_legendItem->setSpacing( 4 );
            d_legendItem->setItemMargin( 2 );
        }
        else
        {
            d_legendItem->setBorderRadius( 8 );
            d_legendItem->setMargin( 4 );
            d_legendItem->setSpacing( 2 );
            d_legendItem->setItemMargin( 0 );
        }

        QFont font = d_legendItem->font();
        font.setPointSize( settings.legendItem.size );
        d_legendItem->setFont( font );
    }
    else
    {
        delete d_legendItem;
        d_legendItem = NULL;
    }

    QwtPlotItemList curveList = itemList( QwtPlotItem::Rtti_PlotCurve );
    if ( curveList.size() != settings.curve.numCurves )
    {
        while ( curveList.size() > settings.curve.numCurves )
        {
            QwtPlotItem* curve = curveList.takeFirst();
            delete curve;
        }

        for ( int i = curveList.size(); i < settings.curve.numCurves; i++ )
            insertCurve();
    }

    curveList = itemList( QwtPlotItem::Rtti_PlotCurve );
    for ( int i = 0; i < curveList.count(); i++ )
    {
        Curve* curve = static_cast<Curve*>( curveList[i] );
        curve->setCurveTitle( settings.curve.title );

        int sz = 0.5 * settings.legendItem.size;
        curve->setLegendIconSize( QSize( sz, sz ) );
    }

    setAutoReplot( false );
    if ( d_isDirty )
    {
        d_isDirty = false;
        replot();
    }
}

要点总结:

  • 进一步熟悉与理解模块化编程
  • 掌握QwtPlotLegendItem的使用方法
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值