QT绘制折现图

做一个小工具,需要根据数据绘制折线图,同时拥有方法缩小拖到等功能

运行结果:

原图:

滚轮缩小

滚轮放大

左移右移

鼠标悬停显示点的坐标

源代码 实现

.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;
}
相关推荐
Pluchon7 分钟前
硅基计划2.0 学习总结 壹 Java初阶
java·开发语言·学习·算法
wowocpp11 分钟前
Java MVC
java·开发语言·mvc
测试者家园13 分钟前
安装Python和配置开发环境
开发语言·软件测试·人工智能·python·职场和发展·零基础·质量效能
筏.k14 分钟前
智能指针入门:深入理解 C++ 的 shared_ptr
开发语言·c++·c#11.0
Rverdoser42 分钟前
代理服务器运行速度慢是什么原因
开发语言·前端·php
牛马baby1 小时前
Java高频面试之并发编程-16
java·开发语言·面试
Blossom.1181 小时前
探索边缘计算:赋能物联网的未来
开发语言·人工智能·深度学习·opencv·物联网·机器学习·边缘计算
饕餮争锋1 小时前
feign.RequestInterceptor 简介-笔记
java·开发语言·笔记
huangyuchi.1 小时前
【C++】智能指针
开发语言·jvm·c++·笔记·c++11·智能指针·shared_ptr
南玖yy2 小时前
C/C++ 内存管理深度解析:从内存分布到实践应用(malloc和new,free和delete的对比与使用,定位 new )
c语言·开发语言·c++·笔记·后端·游戏引擎·课程设计