接笔记1。显示了线后,我想在鼠标悬停在线上的时候,显示所在点的Y轴的值。像下面图这样。
实现方法是这样的。首先继承QChartView类,在类里面添加一个槽函数,用来连接LineSeries上的悬停信号。
QObject::connect(series, SIGNAL(hovered(const QPointF&,bool)), chartView, SLOT(showPos(const QPointF&, bool)));
class ChartView : public QChartView
{
Q_OBJECT
public:
ChartView(QChart *chart, QWidget *parent = 0);
public slots:
void showPos(const QPointF&, bool);
};
void ChartView::showPos(const QPointF& point, bool state)
{
QPoint tempPoint;
tempPoint.setX(qRound(point.x()));
tempPoint.setY(qRound(point.y()));
if (state && static_cast<QSplineSeries*>(this->chart()->series().at(0))->points().contains(tempPoint)) {
QToolTip::showText(QCursor::pos(), QString("%1").arg(tempPoint.y()), this);
}
}
这个槽函数中,首先取值的整数部分,因为点就是整数的值,然后判断点是否在LineSeries上,如果在的话,在鼠标位置显示出来。
类似的,稍作修改也可以显示x轴的值。
下面我们换个复杂一点的。将x轴设置为日期,y轴设置为数值。当鼠标悬停时,显示y轴的数值。
设置日期时需要格式化x轴:
axisX->setFormat(QString("yyyy-MM-dd"));
设置网格是否显示:
axisY_1->setGridLineVisible(true);
axisX->setGridLineVisible(false);
设置坐标轴的颜色和网格的颜色:
axisY_1->setLinePenColor(QColor(Qt::darkCyan));
axisX->setLinePenColor(QColor(Qt::darkCyan));
axisY_1->setGridLineColor(QColor(Qt::darkGray));
#include "mainwindow.h"
#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QPieSeries>
#include <QPieSlice>
#include <QPointF>
#include <QDateTime>
#include <QDate>
#include <QDateTimeAxis>
#include <QDebug>
#include <QSplineSeries>
#include <QToolTip>
#include <QtCharts>
//QT_CHARTS_USE_NAMESPACE //这个宏在Qt5.14能用,在Qt6.3.2报错
QChart *chart;
QSplineSeries *series1;
QChartView *chartView;
void initChart()
{
//初始化QChart的实例
chart = new QChart();
//初始化QSplineSeries的实例
series1 = new QSplineSeries();
//设置两条折线的名称
series1->setName("第一组");
//把曲线添加到QChart的实例chart中
chart->addSeries(series1);
chart->legend()->hide();
//声明并初始化X轴、两个Y轴
QDateTimeAxis *axisX = new QDateTimeAxis();
QValueAxis *axisY_1 = new QValueAxis();
//设置坐标轴显示的范围
axisX->setMin(QDateTime(QDate(2022, 6, 6), QTime()));
axisX->setMax(QDateTime(QDate(2022, 6, 12), QTime()));
axisX->setTickCount(7);
axisX->setFormat(QString("yyyy-MM-dd"));
axisY_1->setMin(0);
axisY_1->setMax(250);
//设置坐标轴上的格点
axisY_1->setTickCount(6);
//设置坐标轴的颜色,粗细,设置网格
axisY_1->setLinePenColor(QColor(Qt::darkCyan));
axisX->setLinePenColor(QColor(Qt::darkCyan));
axisY_1->setGridLineVisible(true);
axisY_1->setGridLineColor(QColor(Qt::darkGray));
axisX->setGridLineVisible(false);
//把坐标轴添加到chart中,
//addAxis函数的第二个参数是设置坐标轴的位置,
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY_1, Qt::AlignLeft);
//把曲线关联到坐标轴
series1->attachAxis(axisX);
series1->attachAxis(axisY_1);
series1->setPointsVisible(true);
// series1->setPointLabelsFormat("@yPoint");
QObject::connect(series1, &QSplineSeries::hovered, [=](const QPointF &point, bool state)mutable{
QPointF tempPoint(point.x(), qRound(point.y()));
QList<int> yList;
for (int i=0; i<series1->points().size(); ++i)
{
yList.append(qRound(series1->points().at(i).y()));
}
int y = qRound(point.y());
if (state)
{
for (int i=0; i<5; ++i)
{
if (yList.contains(y + i))
{
QToolTip::showText(QCursor::pos(), QString("%1").arg(y + i));
break;
}
if (yList.contains(y - i))
{
QToolTip::showText(QCursor::pos(), QString("%1").arg(y - i));
break;
}
}
}
});
chartView = new QChartView(chart);
chartView->setChart(chart);
chartView->setRenderHint(QPainter::Antialiasing);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
initChart();
QDateTime atnowtime = QDateTime(QDate(2022, 6, 6), QTime());
series1->append(atnowtime.toMSecsSinceEpoch(), 225);
QDateTime atnowtime2 = QDateTime(QDate(2022, 6, 7), QTime());
series1->append(atnowtime2.toMSecsSinceEpoch(), 238);
QDateTime atnowtime3 = QDateTime(QDate(2022, 6, 8), QTime());
series1->append(atnowtime3.toMSecsSinceEpoch(), 214);
QDateTime atnowtime4 = QDateTime(QDate(2022, 6, 9), QTime());
series1->append(atnowtime4.toMSecsSinceEpoch(), 226);
QDateTime atnowtime5 = QDateTime(QDate(2022, 6, 10), QTime());
series1->append(atnowtime5.toMSecsSinceEpoch(), 209);
QDateTime atnowtime6 = QDateTime(QDate(2022, 6, 11), QTime());
series1->append(atnowtime6.toMSecsSinceEpoch(), 137);
QDateTime atnowtime7 = QDateTime(QDate(2022, 6, 12), QTime());
series1->append(atnowtime7.toMSecsSinceEpoch(), 90);
MainWindow w;
w.setCentralWidget(chartView);
w.show();
return a.exec();
}
在悬停函数的处理中,由于y轴数值大,一个刻度只占有很小的位置,很难正好悬停到,所以增加了一个范围处理。在点周围上下5的范围内,都会当成点的悬停。
与前一个例子的区别是,这里没有继承QChartView,信号处理函数也改用lambda表达式。
效果: