qwtplot 显示点的数值 Qwt 数据拾取

参考博客:https://blog.csdn.net/czyt1988/article/details/51555020

参考博客:https://blog.csdn.net/tadpole_java/article/details/104937774

SAXYDataTracker.h

#include <qwt_plot_picker.h>
class QwtPlotCurve;
class QwtPlotItem;
class SAXYDataTracker: public QwtPlotPicker
{
public:
    SAXYDataTracker(QWidget * canvas);

protected:
    virtual QwtText trackerTextF(const QPointF & pos) const;
    virtual QRect trackerRect(const QFont & font) const;
    virtual void drawRubberBand (QPainter *painter) const;
    void calcClosestPoint(const QPoint& pos);
private:
    ///
    /// \brief 记录最近点的信息
    ///
    class closePoint
    {
    public:
        closePoint();
        QwtPlotCurve * curve() const{return this->m_curve;}
        void setCurve(QwtPlotCurve * cur);
        bool isValid() const;
        QPointF getClosePoint() const;
        int index() const{return this->m_index;}
        void setIndex(int i){this->m_index = i;}
        double distace() const{return this->m_distace;}
        void setDistace(double d){this->m_distace = d;}
        void setInvalid();
    private:
        QwtPlotCurve *m_curve;
        int m_index;
        double m_distace;
    };
    closePoint m_closePoint;
private slots:
    //捕获鼠标移动的槽
    void mouseMove(const QPoint &pos);
public slots:
    void itemAttached(QwtPlotItem* plotItem,bool on);
};

SAXYDataTracker.cpp

#include "SAXYDataTracker.h"
#include <qwt_plot_item.h>
#include <qwt_plot_curve.h>
#include <qwt_picker_machine.h>
#include <qwt_plot_dict.h>
#include <qwt_plot.h>
#include <qwt_painter.h>
#include <algorithm>
#include <numeric>
SAXYDataTracker::SAXYDataTracker(QWidget* canvas) :
    QwtPlotPicker( canvas )
{
    setTrackerMode( QwtPlotPicker::ActiveOnly );
    setRubberBand( UserRubberBand  );
    setStateMachine( new QwtPickerTrackerMachine() );
    connect (this,&QwtPicker::moved,this,&SAXYDataTracker::mouseMove);
    if(plot ())
        connect (plot(),&QwtPlot::itemAttached,this,&SAXYDataTracker::itemAttached );
}

QwtText SAXYDataTracker::trackerTextF(const QPointF& pos) const
{
    QwtText trackerText;
    if(!m_closePoint.isValid ())
        return trackerText;
    trackerText.setColor( Qt::black );
    QColor lineColor = m_closePoint.curve()->pen ().color ();
    QColor bkColor(lineColor);
    bkColor.setAlpha (30);
    trackerText.setBorderPen( m_closePoint.curve()->pen () );
    trackerText.setBackgroundBrush( bkColor );
    QPointF point = m_closePoint.getClosePoint ();
    QString info = QStringLiteral("<font color=\"%1\">y:%2</font><br>")
                   .arg(lineColor.name ()).arg(point.y ())
                   +
                   QStringLiteral("<font color=\"%1\">x:%2</font>")
                                      .arg(lineColor.name ()).arg(point.x ());
    trackerText.setText( info );
    trackerText.setBorderRadius (5);
    return trackerText;

}

QRect SAXYDataTracker::trackerRect(const QFont& font) const
{
    QRect r = QwtPlotPicker::trackerRect( font );
    r += QMargins(5,5,5,5);
    return r;
}

void SAXYDataTracker::drawRubberBand(QPainter* painter) const
{
    if ( !isActive() || rubberBand() == NoRubberBand ||
        rubberBandPen().style() == Qt::NoPen )
    {
        return;
    }
    if(!m_closePoint.isValid ())
        return;
    QPolygon pickedPoint = pickedPoints ();
    if(pickedPoint.count () < 1)
        return;
    //获取鼠标的客户坐标位置
    const QPoint pos = pickedPoint[0];
    const QPointF closePoint = m_closePoint.getClosePoint ();
    const QPoint cvp = transform (closePoint);
    QwtPainter::drawLine (painter,pos,cvp);
    QRect r(0,0,10,10);
    r.moveCenter (cvp);
    QwtPainter::drawRect (painter,r);
    //QwtPainter::drawEllipse (painter,r);
}

void SAXYDataTracker::calcClosestPoint(const QPoint& pos)
{
    const QwtPlotItemList curveItems =
        plot()->itemList( QwtPlotItem::Rtti_PlotCurve );
    if(curveItems.size () <= 0)
        return;
    //把屏幕坐标转换为图形的数值坐标
    QPointF mousePoint = invTransform(pos);
    //记录最短的距离,默认初始化为double的最大值
    double distance = std::numeric_limits<double>::max ();
    //记录前一次最近点的曲线指针
    QwtPlotCurve * oldCur = m_closePoint.curve ();
    for ( int i = 0; i < curveItems.size(); ++i )
    {
        QwtPlotCurve * cur = static_cast<QwtPlotCurve *>( curveItems[i] );
        int index = cur->closestPoint (pos);
        if(-1 == index)
            continue;
        QPointF p = cur->sample (index);
        QLineF lp(p,mousePoint);
        double l = lp.length ();
        if(l < distance)
        {
            m_closePoint.setDistace(l);
            m_closePoint.setIndex(index);
            m_closePoint.setCurve(cur);
            distance = l;
        }
    }
    //说明最近点的曲线更换了,标记线的颜色换为当前曲线的颜色
    if(m_closePoint.isValid () && oldCur!=m_closePoint.curve ())
    {
        QPen p(m_closePoint.curve ()->pen ());
        p.setWidth (1);
        setRubberBandPen (p);
    }
}

void SAXYDataTracker::mouseMove(const QPoint& pos)
{
    calcClosestPoint(pos);
}

void SAXYDataTracker::itemAttached(QwtPlotItem* plotItem, bool on)
{
    if(!on)
    {
        if(QwtPlotItem::Rtti_PlotCurve == plotItem->rtti ())
        {
            QwtPlotCurve * cur = static_cast<QwtPlotCurve *>( plotItem);
            if(cur == m_closePoint.curve())
                m_closePoint.setInvalid ();
        }
    }
}

SAXYDataTracker::closePoint::closePoint()
  :m_curve(nullptr)
  ,m_index(-1)
  ,m_distace(std::numeric_limits<double>::max ())
{

}

void SAXYDataTracker::closePoint::setCurve(QwtPlotCurve* cur)
{
    this->m_curve = cur;
}

bool SAXYDataTracker::closePoint::isValid() const
{
    return ((this->curve() != nullptr) && (this->index() > 0));
}

QPointF SAXYDataTracker::closePoint::getClosePoint() const
{
    if(isValid ())
        return this->curve()->sample (this->index());
    return QPointF();
}

void SAXYDataTracker::closePoint::setInvalid()
{
    setCurve (nullptr);
    setIndex (-1);
    setDistace (std::numeric_limits<double>::max ());
}

main.cpp

#include <QApplication>
#include <QtWidgets>
#include <qwt_plot.h>
#include <qwt_scale_div.h>
#include <qwt_plot_curve.h>
#include <qwt_point_data.h>
#include <qwt_scale_engine.h>
#include <qwt_plot_picker.h>
#include <qwt_symbol.h>
#include "SAXYDataTracker.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QwtPlot *poPlot = new QwtPlot;

    /* Set Log Scale */
    poPlot->setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine() );
    poPlot->setAxisScaleEngine( QwtPlot::yLeft,   new QwtLogScaleEngine() );

    poPlot->enableAxis(QwtPlot::xBottom , true);
    poPlot->enableAxis(QwtPlot::yLeft   , true);

    (void) new SAXYDataTracker(poPlot->canvas());

    QList<double> adF;

    adF = {0.06125, 0.125,0.25,0.5,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192};

    qSort(adF);

     /* Fill ticks */
    QList<double> adTicks[QwtScaleDiv::NTickTypes];
    adTicks[QwtScaleDiv::MajorTick] = adF;
    QwtScaleDiv oScaleDiv( adTicks[QwtScaleDiv::MajorTick].last(),
            adTicks[QwtScaleDiv::MajorTick].first(),
            adTicks );

    poPlot->setAxisScaleDiv( QwtPlot::xBottom, oScaleDiv );


    /* Curve title, cut MCSD_ & suffix*/
    const QwtText oTxtTitle( "test" );

    /* Create a curve pointer */
    QwtPlotCurve *poCurve = NULL;
    poCurve = new QwtPlotCurve( oTxtTitle );

    poCurve->setPen( Qt::black, 2, Qt::SolidLine );
    poCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );

    QwtSymbol *poSymbol = new QwtSymbol( QwtSymbol::Ellipse,
                                         QBrush( Qt::yellow ),
                                         QPen( Qt::blue, 2 ),
                                         QSize( 8, 8 ) );
    poCurve->setSymbol( poSymbol );
    poCurve->setStyle(QwtPlotCurve::Lines);

    QPolygonF aoPointF;
    aoPointF.clear();

    for(int i = 0 ; i < adF.count();i++)
    {
        QPointF oPoinF;

        oPoinF.setX(adF.at(i));
        oPoinF.setY(pow(adF.at(i),3.14));

        aoPointF.append(oPoinF);
    }

    poCurve->setSamples( aoPointF );
    poCurve->setAxes(QwtPlot::xBottom, QwtPlot::yLeft);
    poCurve->attach(poPlot);
    poCurve->setVisible( true );

    poPlot->show();

    return a.exec();
}
文章目录