QChat realizes cursor movement + controllable cross cursor length

This is achieved by rewriting QChartView and inheriting the mousePressEvent and mouseMoveEvent functions to control the cursor length;
The environment used is QT5.14.2, and the package used is: MSVC2017 64bit, win10 system;
Above code:

//Chart display close to label
callout.h

#ifndef CALLOUT_H
#define CALLOUT_H

#include <QtCharts/QChartGlobal>
#include <QtWidgets/QGraphicsItem>
#include <QtGui/QFont>
#include <QDebug>

QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE

class Callout: public QGraphicsItem
{<!-- -->
public:
    Callout(QChart *parent);

    void setText(const QString & amp;text);
    void setAnchor(QPointF point);
    void updateGeometry();

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

private:
    QString m_text;
    QRectF m_textRect;
    QRectF m_rect;
    QPointF m_anchor;
    QFont m_font;
    QChart *m_chart;
};

#endif // CALLOUT_H

callout.h

#include "callout.h"
#include <QtGui/QPainter>
#include <QtGui/QFontMetrics>
#include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtGui/QMouseEvent>
#include <QtCharts/QChart>

Callout::Callout(QChart *chart):
    QGraphicsItem(chart),
    m_chart(chart)
{<!-- -->
}

QRectF Callout::boundingRect() const
{<!-- -->
    QPointF anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
    QRectFrect;
    rect.setLeft(qMin(m_rect.left(), anchor.x()));
    rect.setRight(qMax(m_rect.right(), anchor.x()));
    rect.setTop(qMin(m_rect.top(), anchor.y()));
    rect.setBottom(qMax(m_rect.bottom(), anchor.y()));
    return rect;
}

void Callout::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{<!-- -->
    Q_UNUSED(option)
    Q_UNUSED(widget)
    QPainterPath path;
    path.addRoundedRect(m_rect, 5, 5);

    QPointF anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
    qDebug()<<"\t\t\t anchor = "<<anchor;
    if (!m_rect.contains(anchor)) {<!-- -->
        QPointF point1, point2;

        // establish the position of the anchor point in relation to m_rect
        bool above = anchor.y() <= m_rect.top();
        bool aboveCenter = anchor.y() > m_rect.top() & amp; & amp; anchor.y() <= m_rect.center().y();
        bool belowCenter = anchor.y() > m_rect.center().y() & amp; & amp; anchor.y() <= m_rect.bottom();
        bool below = anchor.y() > m_rect.bottom();

        bool onLeft = anchor.x() <= m_rect.left();
        bool leftOfCenter = anchor.x() > m_rect.left() & amp; & amp; anchor.x() <= m_rect.center().x();
        bool rightOfCenter = anchor.x() > m_rect.center().x() & amp; & amp; anchor.x() <= m_rect.right();
        bool onRight = anchor.x() > m_rect.right();

        // get the nearest m_rect corner.
        qreal x = (onRight + rightOfCenter) * m_rect.width();
        qreal y = (below + belowCenter) * m_rect.height();
        bool cornerCase = (above & amp; & amp; onLeft) || (above & amp; & amp; onRight) || (below & amp; & amp; onLeft) || (below & amp; & amp; onRight);
        bool vertical = qAbs(anchor.x() - x) > qAbs(anchor.y() - y);

        qreal x1 = x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * !vertical * (onLeft * 10 - onRight * 20);
        qreal y1 = y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (above * 10 - below * 20);;
        point1.setX(x1);
        point1.setY(y1);

        qreal x2 = x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * !vertical * (onLeft * 20 - onRight * 10);;
        qreal y2 = y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (above * 20 - below * 10);;
        point2.setX(x2);
        point2.setY(y2);

        path.moveTo(point1);
        path.lineTo(anchor);
        path.lineTo(point2);
        path = path.simplified();
    }
    painter->setBrush(QColor(255, 255, 255));
    painter->drawPath(path);
    painter->drawText(m_textRect, m_text);
}

void Callout::mousePressEvent(QGraphicsSceneMouseEvent *event)
{<!-- -->
    event->setAccepted(true);
}

void Callout::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{<!-- -->
    if (event->buttons() & amp; Qt::LeftButton){<!-- -->
        setPos(mapToParent(event->pos() - event->buttonDownPos(Qt::LeftButton)));
        event->setAccepted(true);
    } else {<!-- -->
        event->setAccepted(false);
    }
}

void Callout::setText(const QString & amp;text)
{<!-- -->
    m_text = text;
    QFontMetrics metrics(m_font);
    m_textRect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt::AlignLeft, m_text);
    m_textRect.translate(5, 5);
    prepareGeometryChange();
    m_rect = m_textRect.adjusted(-5, -5, 5, 5);
}

void Callout::setAnchor(QPointF point)
{<!-- -->
    m_anchor = point;
}

void Callout::updateGeometry()
{<!-- -->
    prepareGeometryChange();
    setPos(m_chart->mapToPosition(m_anchor) + QPoint(10, -50));
}

//Rewritten QChartView class
mychartview_mp.h

#ifndef MYCHARTVIEW_MP_H
#defineMYCHARTVIEW_MP_H

#include <QDebug>
#include <QtCharts/QChartView>
#include <QtCharts/QPieSeries>
#include <QtCharts/QPieSlice>
#include <QtCharts/QAbstractBarSeries>
#include <QtCharts/QPercentBarSeries>
#include <QtCharts/QStackedBarSeries>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLineSeries>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QAreaSeries>
#include <QtCharts/QLegend>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtCore/QRandomGenerator>
#include <QtCharts/QBarCategoryAxis>
#include <QtWidgets/QApplication>
#include <QtCharts/QValueAxis>

#include "callout.h"

QT_BEGIN_NAMESPACE
namespace Ui {<!-- --> class MainWindow; }
QT_END_NAMESPACE

QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
class Ui_ThemeWidgetForm;
QT_END_NAMESPACE


QT_CHARTS_BEGIN_NAMESPACE
class QChartView;
class QChart;
//class myChartViewPrivate;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE


class myChartView_mp : public QChartView
{<!-- -->
    Q_OBJECT
public:
    //explicit myChartView(QWidget *parent = nullptr);
    myChartView_mp(QWidget *parent = nullptr);
    ~myChartView_mp();
    //Text annotation
    Callout *pcal;
protected:
    //mouse event
    void mousePressEvent(QMouseEvent *event) override;
    //void mouseDoubleClickEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
private:
    Q_DISABLE_COPY(myChartView_mp)
    QGraphicsLineItem x_line;
    QGraphicsLineItem y_line;

    int x_b;
    int x_e;
    int y_b;
    int y_e;
    QPointF pot;
public slots:
    void tooltip(QPointF point, bool state);
};

#endif // MYCHARTVIEW_MP_H

mychartview_mp.cpp

#include "mychartview_mp.h"

myChartView_mp::myChartView_mp(QWidget *parent) : QChartView(parent)
{<!-- -->
    QPen redPen(QColor( 159, 252, 253 ));
    redPen.setWidth(1);
    x_line.setPen(redPen);
    x_line.setZValue(2);
    y_line.setPen(redPen);
    y_line.setZValue(2);

    this->scene()->addItem( & amp;x_line);
    this->scene()->addItem( & y_line);
}
myChartView_mp::~myChartView_mp()
{<!-- -->

}


//Mouse press event
void myChartView_mp::mousePressEvent(QMouseEvent *event)
{<!-- -->
    QChartView::mousePressEvent(event);
}




void myChartView_mp::mouseMoveEvent(QMouseEvent *event)
{<!-- -->
    pot = event->pos();
    x_b = this->chart()->plotArea().x();
    x_e = x_b + this->chart()->plotArea().width();
    y_b = this->chart()->plotArea().y();
    y_e = y_b + this->chart()->plotArea().height();
    if ((pot.rx() < x_b) || (pot.rx() > x_e) || (pot.ry() < y_b) || (pot.ry() > y_e))
    {<!-- -->
        x_line.setVisible(false);
        y_line.setVisible(false);
        return;
    }
    x_line.setVisible(true);
    y_line.setVisible(true);
    //Call the overridden method of the parent class. This line of program is different from e->ignore(). Ignore continues to pass the event to the parent control (generally the parent control is the UI interface) instead of passing it to the parent class.
    QChartView::mouseMoveEvent(event);
    x_line.setLine(pot.rx(),y_b,pot.rx(),y_e);
    y_line.setLine(x_b,pot.ry(),x_e,pot.ry());
    QPointF pp1 = this->chart()->mapToValue(pot);
    //qDebug()<<"x = "<<pot.rx()<<"y = "<<pot.ry()<<QDateTime::fromMSecsSinceEpoch(pp1.rx())<< pp1.ry();
    //this->chart()->mapToScene(pot);
    //pcal->setText(QString("X: %1 \\
Y: %2 ").arg(pot.rx()).arg(pot.ry()));
    //pcal->setAnchor(QPoint(pot.rx(),pot.ry()));
    //pcal->show();

}

void myChartView_mp::tooltip(QPointF point, bool state)
{<!-- -->
    if(state)
    {<!-- -->
        pcal = new Callout(this->chart());
        pcal->setText(QString("X: %1 \\
Y: %2 ").arg(point.x()).arg(point.y()));
        pcal->setAnchor(point);
        pcal->setZValue(11);
        pcal->updateGeometry();
        pcal->show();
        //qDebug()<<"\t\t[tooltip]"<<point.x()<<point.y()<<this->chart();
    } else
    {<!-- -->
        pcal->hide();
    }
}

//Main window
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtCharts>

#include "mychartview_mp.h"

QT_BEGIN_NAMESPACE
namespace Ui {<!-- --> class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{<!-- -->
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{<!-- -->
    ui->setupUi(this);

    //Create a series of points for the curve
    QSplineSeries *plSer = new QSplineSeries();
    plSer->setName("curve");
// double xx[100] = {6.91,12.79,20.63,28.47,38.27,44.15,51.99,59.83,67.67,73.55,81.39,89.23,97.07,104.91,112.75,122.55,128.43,134.31,1 42.15,148.03,
// 157.83,165.67,171.55,181.35,187.23,193.11,202.91,212.71,218.59,226.43,234.27,240.15,249.95,253.87,263.67,273.47,281.31,287 .19,293.07,300.91,
// 306.79,318.55,326.39,334.23,336.19,349.91,355.79,363.63,369.51,373.43,385.19,387.15,400.87,408.71,416.55,422.43,428.31,438 .11,442.03,447.91,
// 461.63,469.47,475.35,481.23,492.99,498.87,508.67,516.51,518.47,530.23,538.07,541.99,551.79,559.63,565.51,567.47,579.23,590 .99,596.87,602.75,
// 610.59,620.39,624.31,636.07,638.03,651.75,657.63,661.55,673.31,681.15,687.03,690.95,700.75,708.59,718.39,726.23,730.15,739 .95,751.71,755.63};
// double yy[100];

// for (int i = 1;i < 101;i + + )
// {<!-- -->
// yy[i - 1] = i * 100.00;
// plSer->append(yy[i - 1],xx[i - 1]);
// }

    double xx[9] = {<!-- -->150.03,163.517,197.535,221.18,231.506,285.653,284.863,362.173,481.254};
    double yy[9] = {<!-- -->90.0,100.0,120.0,140.0,150.0,180.0,200.0,220.0,300.0};
    for (int i = 0;i < 9;i + + ) {<!-- -->
        plSer->append(yy[i],xx[i]);
    }
    //Create chart object
    QChart *pqchar = new QChart();
    pqchar->legend()->hide();
    pqchar->addSeries(plSer);
    // pqchar->setTitle(QString::fromLocal8Bit("curve"));
    pqchar->setTitle("112343");
    pqchar->createDefaultAxes();
    pqchar->axisY()->setRange(0,500);

    //QChartView * pview = new QChartView(pqchar);
    myChartView_mp * pview = new myChartView_mp();
    pview->setChart(pqchar);
    pview->setRenderHint(QPainter::Antialiasing);
    ui->horizontalLayout->addWidget(pview);
    connect(plSer, & amp;QLineSeries::hovered, pview, & amp;myChartView_mp::tooltip);
}

MainWindow::~MainWindow()
{<!-- -->
    delete ui;
}


main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{<!-- -->
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


The above content refers to the content of at least two netizens. It has been too long and I have forgotten which one it is. I would like to express my gratitude!