首先上图看下要实现的效果:
即图中有两条曲线,鼠标点击后显示横坐标的值,以及与两条曲线交点的纵坐标的值。注意:本例只是实现了坐标值的显示,所以显示的值和曲线值不符,鼠标点击的事件可以自行实现。
参照网址:http://www.qcustomplot.com/index.php/tutorials/specialcases/axistags 的方法,稍加改编实现。
主要步骤:
1.在qt中添加类TagAxis,内容如下
tagaxis.h
#ifndef TAGAXIS_H
#define TAGAXIS_H
#include <QObject>
#include "qcustomplot.h"
class TagAxis : public QObject
{
Q_OBJECT
public:
explicit TagAxis(QCPAxis *parentAxis);
virtual ~TagAxis();
// setters:
void setPen(const QPen &pen);
void setBrush(const QBrush &brush);
void setTextY1(const QString &text);
void setTextY2(const QString &text);
void setTextX(const QString &text);
void updatePosition(double valueY1,double valueY2,double valueX);
signals:
public slots:
protected:
QCPAxis *mAxis;
int yAxisCount;
QPointer<QCPItemTracer> mDummyTracerY1;
QPointer<QCPItemText> mLabelY1;
QPointer<QCPItemTracer> mDummyTracerY2;
QPointer<QCPItemText> mLabelY2;
QPointer<QCPItemTracer> mDummyTracerX;
QPointer<QCPItemText> mLabelX;
};
#endif // TAGAXIS_H
tagaxis.cpp
#include "tagaxis.h"
TagAxis::TagAxis(QCPAxis *parentAxis) : QObject(parentAxis),
mAxis(parentAxis)
{
mDummyTracerY1 = new QCPItemTracer(mAxis->parentPlot());
mDummyTracerY1->setVisible(true);
mDummyTracerY1->position->setTypeX(QCPItemPosition::ptAxisRectRatio);//QCPItemPosition::ptPlotCoords
mDummyTracerY1->position->setTypeY(QCPItemPosition::ptPlotCoords);
mDummyTracerY1->position->setAxisRect(mAxis->axisRect());
mDummyTracerY1->position->setAxes(0, mAxis);
mLabelY1 = new QCPItemText(mAxis->parentPlot());
mLabelY1->setLayer("overlay");
mLabelY1->setClipToAxisRect(false);
mLabelY1->setPadding(QMargins(3, 0, 3, 0));
mLabelY1->setBrush(QBrush(Qt::white));
mLabelY1->setPen(QPen(Qt::blue));
mLabelY1->setPositionAlignment(Qt::AlignRight|Qt::AlignVCenter);
mLabelY1->position->setTypeX(QCPItemPosition::ptAxisRectRatio);//QCPItemPosition::ptPlotCoords
mLabelY1->position->setTypeY(QCPItemPosition::ptPlotCoords);
mDummyTracerY2 = new QCPItemTracer(mAxis->parentPlot());
mDummyTracerY2->setVisible(true);
mDummyTracerY2->position->setTypeX(QCPItemPosition::ptAxisRectRatio);//QCPItemPosition::ptPlotCoords
mDummyTracerY2->position->setTypeY(QCPItemPosition::ptPlotCoords);
// mDummyTracerY1->position->setAxisRect(mAxis->axisRect());
// mDummyTracerY1->position->setAxes(0, mAxis);
mLabelY2 = new QCPItemText(mAxis->parentPlot());
mLabelY2->setLayer("overlay");
mLabelY2->setClipToAxisRect(false);
mLabelY2->setPadding(QMargins(3, 0, 3, 0));
mLabelY2->setBrush(QBrush(Qt::white));
mLabelY2->setPen(QPen(Qt::blue));
mLabelY2->setPositionAlignment(Qt::AlignRight|Qt::AlignVCenter);
mLabelY2->position->setTypeX(QCPItemPosition::ptAxisRectRatio);//QCPItemPosition::ptPlotCoords
mLabelY2->position->setTypeY(QCPItemPosition::ptPlotCoords);
mDummyTracerX = new QCPItemTracer(mAxis->parentPlot());
mDummyTracerX->setVisible(true);
mDummyTracerX->position->setTypeX(QCPItemPosition::ptPlotCoords);//QCPItemPosition::ptPlotCoords
mDummyTracerX->position->setTypeY(QCPItemPosition::ptAxisRectRatio);
// mDummyTracerX->position->setAxisRect(mAxis->axisRect());
// mDummyTracerX->position->setAxes(0, mAxis);
mLabelX = new QCPItemText(mAxis->parentPlot());
mLabelX->setLayer("overlay");
mLabelX->setClipToAxisRect(false);
mLabelX->setPadding(QMargins(3, 0, 3, 0));
mLabelX->setBrush(QBrush(Qt::white));
mLabelX->setPen(QPen(Qt::blue));
mLabelX->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);
mLabelX->position->setTypeX(QCPItemPosition::ptPlotCoords);//QCPItemPosition::ptPlotCoords
mLabelX->position->setTypeY(QCPItemPosition::ptAxisRectRatio);
}
TagAxis::~TagAxis()
{
if (mDummyTracerY1)
mDummyTracerY1->parentPlot()->removeItem(mDummyTracerY1);
if (mLabelY1)
mLabelY1->parentPlot()->removeItem(mLabelY1);
if (mDummyTracerY2)
mDummyTracerY2->parentPlot()->removeItem(mDummyTracerY2);
if (mLabelY2)
mLabelY2->parentPlot()->removeItem(mLabelY2);
if (mDummyTracerX)
mDummyTracerX->parentPlot()->removeItem(mDummyTracerX);
if (mLabelX)
mLabelX->parentPlot()->removeItem(mLabelX);
}
void TagAxis::setPen(const QPen &pen)
{
mLabelY1->setPen(pen);
mLabelY2->setPen(pen);
mLabelX->setPen(pen);
}
void TagAxis::setBrush(const QBrush &brush)
{
mLabelY1->setBrush(brush);
mLabelY2->setBrush(brush);
mLabelX->setBrush(brush);
}
void TagAxis::setTextY1(const QString &text)
{
mLabelY1->setText(text);
}
void TagAxis::setTextY2(const QString &text)
{
mLabelY2->setText(text);
}
void TagAxis::setTextX(const QString &text)
{
mLabelX->setText(text);
}
void TagAxis::updatePosition(double valueY1,double valueY2,double valueX)
{
mDummyTracerY1->position->setCoords(0, valueY1);
mLabelY1->position->setCoords(0,valueY1);
mDummyTracerY2->position->setCoords(0, valueY2);
mLabelY2->position->setCoords(0,valueY2);
mDummyTracerX->position->setCoords(valueX,1);
mLabelX->position->setCoords(valueX,1);
}
2.在主文件中引用
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qcustomplot.h"
#include "axistag.h"
#include "tagaxis.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void timerSlot();
private:
Ui::MainWindow *ui;
QCustomPlot *mPlot;
QPointer<QCPGraph> mGraph1;
QPointer<QCPGraph> mGraph2;
// AxisTag *mTag1;
// AxisTag *mTag2;
TagAxis *tagAxis;
QTimer mDataTimer;
};
#endif // MAINWINDOW_H
mainwindow.cpp中实现:
ui->setupUi(this);
mPlot = new QCustomPlot(this);
setCentralWidget(mPlot);
connect(mPlot->yAxis2, SIGNAL(rangeChanged(QCPRange)), mPlot->yAxis, SLOT(setRange(QCPRange)));
connect(mPlot->yAxis2, SIGNAL(rangeChanged(QCPRange)), mPlot->yAxis2, SLOT(setRange(QCPRange)));
mPlot->yAxis2->setVisible(true);
mPlot->addGraph();
mPlot->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graph
mPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue
mPlot->addGraph();
mPlot->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph
tagAxis = new TagAxis(mPlot->graph(0)->valueAxis());
tagAxis->setPen(mPlot->graph(0)->pen());
QVector<double> x(251), y0(251), y1(251);
for (int i=0; i<251; ++i)
{
x[i] = i;
y0[i] = qExp(-i/150.0)*qCos(i/10.0); // exponentially decaying cosine
y1[i] = qExp(-i/150.0); // exponential envelope
}
mPlot->xAxis2->setVisible(true);
mPlot->xAxis2->setTickLabels(false);
mPlot->yAxis2->setVisible(true);
mPlot->yAxis2->setTickLabels(false);
// make left and bottom axes always transfer their ranges to right and top axes:
connect(mPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), mPlot->xAxis2, SLOT(setRange(QCPRange)));
connect(mPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), mPlot->yAxis2, SLOT(setRange(QCPRange)));
// pass data points to graphs:
mPlot->graph(0)->setData(x, y0);
mPlot->graph(1)->setData(x, y1);
// let the ranges scale themselves so graph 0 fits perfectly in the visible area:
mPlot->graph(0)->rescaleAxes();
// same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
mPlot->graph(1)->rescaleAxes(true);
// Note: we could have also just called customPlot->rescaleAxes(); instead
// Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
mPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
tagAxis->setTextY1("-0.3");
tagAxis->setTextY2("0.6");
tagAxis->setTextX("125");
tagAxis->updatePosition(-0.3,0.6,125);
mPlot->replot();
完毕!
完整工程代码github地址:https://github.com/cloudsmile/axisTest