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;
}
相关推荐
万物复苏10118 分钟前
【汇编】c++游戏开发
开发语言·笔记·游戏·c
水w1 小时前
单例模式的几种实现方式
java·开发语言·jvm·单例模式·单例
monkey_meng2 小时前
【Rust中的策略模式实现】
开发语言·rust·策略模式
吃汉堡吃到饱3 小时前
【Android】EventBus事件总线用法浅析
android·开发语言
这猪好帅3 小时前
【项目组件】第三方库——websocketpp
开发语言·c++
原来是猿4 小时前
类和对象(中)
c语言·开发语言·数据结构·c++
IT猿手5 小时前
多目标优化算法:多目标鹅算法(MOGOOSE)求解UF1-UF10,提供完整MATLAB代码
开发语言·算法·matlab·多目标算法
水w5 小时前
VuePress v2 快速搭建属于自己的个人博客网站
开发语言·前端·vue·vuepress
羊小猪~~6 小时前
前端入门一之ES6--递归、浅拷贝与深拷贝、正则表达式、es6、解构赋值、箭头函数、剩余参数、String、Set
开发语言·前端·javascript·css·正则表达式·html·es6
code_shenbing7 小时前
跨平台WPF框架Avalonia教程 十四
开发语言·ui·c#·wpf