I've created a custom 'QCPCursor' class that inherit from QCPItemStraightLine. In this class I add a QCPItemText object and anchor it to the QCPItemPosition point1. Then it react to the mouseMoveEvent to set the coordinates and replot. To improve performance I only replot this layer (lmBuffered). This code can most likely be improved.
void Plot::build_cursor() {
// Create separate layer to only replot this when moving the cursor
qcpplot->addLayer("cursorLayer", 0, QCustomPlot::limAbove);
qcpplot->layer("cursorLayer")->setMode(QCPLayer::lmBuffered);
cursora = new QCPCursor(qcpplot, Qt::Orientation::Vertical, "A", 2);
cursorb = new QCPCursor(qcpplot, Qt::Orientation::Vertical, "B", 4);
qcpplot->replot();
}
qcpcursor.h
#ifndef QCPCURSOR_H
#define QCPCURSOR_H
#include "qcustomplot.h"
#include <QMouseEvent>
#include <QPointF>
#include <QVariant>
#include <QtCore>
#include <QtGui>
class QMouseEvent;
class QVariant;
class QPointF;
class QCPCursor : public QCPItemStraightLine {
Q_OBJECT
public:
QCPCursor(QCustomPlot* parentPlot, Qt::Orientation orientation, QString name, double coordxy_initial);
~QCPCursor();
Qt::Orientation orientation() const { return orientation_; }
void setCoordsFromPosEmitAndReplot(QPointF const& pos);
void setCoordsXAndReplot(double x);
void setCoordsYAndReplot(double y);
double coord_x;
double coord_y;
signals:
void coordXChanged(double x);
void coordYChanged(double y);
protected:
Qt::Orientation orientation_;
QCPItemText* text;
protected slots:
void mousePressEvent(QMouseEvent* event, QVariant const& details);
void mouseMoveEvent(QMouseEvent* event, QPointF const& startPos);
void mouseReleaseEvent(QMouseEvent* event, QPointF const& startPos);
};
#endif // QCPCURSOR_H
qcpcursor.cpp
#include "qcpcursor.h"
QCPCursor::QCPCursor(QCustomPlot* parentPlot, Qt::Orientation orientation, QString name, double coordxy_initial)
: QCPItemStraightLine(parentPlot) {
this->orientation_ = orientation;
this->setLayer("cursorLayer");
this->setClipToAxisRect(false);
QPen pen(Qt::lightGray);
pen.setWidth(1); // Best performance with 1 width
this->setPen(pen);
// QCPItemText for cursor "name" (Normally A and B)
text = new QCPItemText(parentPlot);
text->setLayer("cursorLayer");
text->setPositionAlignment(Qt::AlignHCenter | Qt::AlignCenter);
text->setBrush(QBrush(Qt::lightGray));
text->setColor(Qt::black);
QFont font;
font.setStyleHint(QFont::Helvetica);
font.setBold(false);
font.setPointSize(12);
text->setFont(font);
text->setText(name);
text->position->setTypeX(QCPItemPosition::PositionType::ptAxisRectRatio);
text->position->setTypeY(QCPItemPosition::PositionType::ptAxisRectRatio);
text->position->setCoords(0, 0.05);
text->position->setParentAnchorX(this->point1);
if (orientation_ == Qt::Vertical) {
coord_x = coordxy_initial;
coord_y = 0;
point1->setCoords(coord_x, 0);
point2->setCoords(coord_x, 1);
} else {
coord_x = 0;
coord_y = coordxy_initial;
point1->setCoords(0, coord_y);
point2->setCoords(1, coord_y);
}
}
QCPCursor::~QCPCursor() {
}
void QCPCursor::setCoordsFromPosEmitAndReplot(QPointF const& pos) {
if (orientation() == Qt::Vertical) {
coord_x = parentPlot()->xAxis->pixelToCoord(pos.x());
coord_y = 0;
point1->setCoords(coord_x, 0);
point2->setCoords(coord_x, 1);
// Emit that the coordination has changed
emit(coordXChanged(coord_x));
} else {
coord_x = 0;
coord_y = parentPlot()->yAxis->pixelToCoord(pos.y());
point1->setCoords(0, coord_y);
point2->setCoords(1, coord_y);
// Emit that the coordination has changed
emit(coordYChanged(coord_y));
}
// Only replot the layer with the cursor
// https://www.qcustomplot.com/documentation/performanceimprovement.html
parentPlot()->layer("cursorLayer")->replot();
}
void QCPCursor::setCoordsXAndReplot(double x) {
if (orientation() == Qt::Vertical) {
coord_x = x;
coord_y = 0;
point1->setCoords(coord_x, 0);
point2->setCoords(coord_x, 1);
// Do NOT emit when using this function (will cause infinite loop as this function is called to sync cursors for multiple plots when the signal coordXChanged is emitted)
parentPlot()->layer("cursorLayer")->replot();
}
}
void QCPCursor::setCoordsYAndReplot(double y) {
if (orientation() == Qt::Horizontal) {
coord_x = 0;
coord_y = y;
point1->setCoords(0, coord_y);
point2->setCoords(1, coord_y);
// Do NOT emit when using this function (will cause infinite loop as this function is called to sync cursors for multiple plots when the signal coordYChanged is emitted)
parentPlot()->layer("cursorLayer")->replot();
}
}
void QCPCursor::mousePressEvent(QMouseEvent* event, QVariant const& details) {
}
void QCPCursor::mouseMoveEvent(QMouseEvent* event, QPointF const& startPos) {
setCoordsFromPosEmitAndReplot(event->pos());
}
void QCPCursor::mouseReleaseEvent(QMouseEvent* event, QPointF const& startPos) {
}