做一个小工具,需要根据数据绘制折线图,同时拥有方法缩小拖到等功能
运行结果:
原图:
滚轮缩小
滚轮放大
左移右移
鼠标悬停显示点的坐标
源代码 实现
.pro 使用QChart 加入其对应的模块
QT += charts
customchartview:继承chartView 重写了鼠标点击,鼠标释放,鼠标移动,滑轮事件,构建了点击显示提示框的函数
#ifndef CUSTOMCHARTVIEW_H
#define CUSTOMCHARTVIEW_H
#include <QChartView>
#include <QMouseEvent>
#include <QWheelEvent>
QT_BEGIN_NAMESPACE
namespace QtCharts {
class QChart;
}
QT_END_NAMESPACE
class CustomChartView : public QtCharts::QChartView {
Q_OBJECT
public:
explicit CustomChartView(QtCharts::QChart *chart, QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
private:
void updateToolTip(const QPoint &point);
bool m_dragging;
QPoint m_lastPos;
QtCharts::QChart *m_chart;
};
#endif // CUSTOMCHARTVIEW_H
.h
#include "customchartview.h"
#include <QtCharts/QChart>
#include <QtCharts/QValueAxis>
#include <QToolTip>
#include <QXYSeries>
CustomChartView::CustomChartView(QtCharts::QChart *chart, QWidget *parent)
: QChartView(chart, parent), m_dragging(false), m_chart(chart)
{
}
void CustomChartView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_dragging = true;
m_lastPos = event->pos();
}
}
void CustomChartView::mouseMoveEvent(QMouseEvent *event)
{
updateToolTip(event->pos());
if (m_dragging) {
QPoint delta = event->pos() - m_lastPos;
if (chart()->axes(Qt::Horizontal).isEmpty() || chart()->axes(Qt::Vertical).isEmpty()) {
return;
}
QtCharts::QValueAxis *axisX = qobject_cast<QtCharts::QValueAxis*>(chart()->axes(Qt::Horizontal).first());
QtCharts::QValueAxis *axisY = qobject_cast<QtCharts::QValueAxis*>(chart()->axes(Qt::Vertical).first());
if (axisX && axisY) {
qreal rangeX = axisX->max() - axisX->min();
qreal rangeY = axisY->max() - axisY->min();
// 修正平移方向
axisX->setRange(axisX->min() - delta.x() * rangeX / width(),
axisX->max() - delta.x() * rangeX / width());
axisY->setRange(axisY->min() + delta.y() * rangeY / height(),
axisY->max() + delta.y() * rangeY / height());
}
m_lastPos = event->pos();
}else{
updateToolTip(event->pos());
}
}
void CustomChartView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_dragging = false;
}
}
void CustomChartView::wheelEvent(QWheelEvent *event)
{
if (chart()->axes(Qt::Horizontal).isEmpty() || chart()->axes(Qt::Vertical).isEmpty()) {
return;
}
QtCharts::QValueAxis *axisX = qobject_cast<QtCharts::QValueAxis*>(chart()->axes(Qt::Horizontal).first());
QtCharts::QValueAxis *axisY = qobject_cast<QtCharts::QValueAxis*>(chart()->axes(Qt::Vertical).first());
if (axisX && axisY) {
qreal factor = event->angleDelta().y() > 0 ? 0.9 : 1.1;
qreal rangeX = axisX->max() - axisX->min();
qreal rangeY = axisY->max() - axisY->min();
axisX->setRange(axisX->min() + rangeX * (1 - factor) / 2,
axisX->max() - rangeX * (1 - factor) / 2);
axisY->setRange(axisY->min() + rangeY * (1 - factor) / 2,
axisY->max() - rangeY * (1 - factor) / 2);
}
QChartView::wheelEvent(event);
}
void CustomChartView::updateToolTip(const QPoint &point)
{
// 将鼠标位置映射到图表坐标值
QPointF chartPoint = chart()->mapToValue(point);
qreal x = chartPoint.x();
qreal y = chartPoint.y();
// 遍历图表中的系列
foreach (auto series, chart()->series()) {
// 检查系列是否是 QXYSeries 类型
QtCharts::QXYSeries *xySeries = qobject_cast<QtCharts::QXYSeries *>(series);
if (xySeries) {
// 遍历所有点
for (int i = 0; i < xySeries->count(); ++i) {
QPointF pointF = xySeries->at(i);
// 检查鼠标是否在当前点附近
if (QRectF(pointF.x() - 5, pointF.y() - 5, 10, 10).contains(chartPoint)) {
// 显示提示框
QToolTip::showText(mapToGlobal(point), QString("X: %1, Y: %2").arg(x).arg(y));
return;
}
}
}
}
// 如果没有鼠标悬停在任何数据点上,则隐藏提示
QToolTip::hideText();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QChart>
#include <QMainWindow>
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;
QtCharts::QChart * chart;
};
#endif // MAINWINDOW_H
mainwindow.c :创建些随机数,加入x轴和y轴,设置点和线的颜色
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "customchartview.h"
#include <QtCharts/QChart>
#include <QtCharts/QLineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QValueAxis>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 创建图表和系列
QtCharts::QChart *chart = new QtCharts::QChart();
QtCharts::QLineSeries *lineSeries = new QtCharts::QLineSeries();
QtCharts::QScatterSeries *scatterSeries = new QtCharts::QScatterSeries();
// 添加数据点到系列
QList<QPointF> points = { {0, 0}, {1, 1}, {2, 0}, {3, 1} };
for (const auto &point : points) {
lineSeries->append(point);
scatterSeries->append(point);
}
// 设置连线颜色
lineSeries->setColor(Qt::red);
scatterSeries->setColor(Qt::blue);
// 将系列添加到图表中
chart->addSeries(lineSeries);
chart->addSeries(scatterSeries);
// 配置 X 轴和 Y 轴
QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis();
axisX->setTitleText("X 轴");
chart->addAxis(axisX, Qt::AlignBottom);
lineSeries->attachAxis(axisX);
scatterSeries->attachAxis(axisX);
QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis();
axisY->setTitleText("Y 轴");
chart->addAxis(axisY, Qt::AlignLeft);
lineSeries->attachAxis(axisY);
scatterSeries->attachAxis(axisY);
// 创建自定义图表视图
CustomChartView *chartView = new CustomChartView(chart);
// 设置布局
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(chartView);
QWidget *centralWidget = new QWidget();
centralWidget->setLayout(layout);
setCentralWidget(centralWidget);
}
MainWindow::~MainWindow()
{
delete ui;
}