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;
}
相关推荐
李小小钦7 分钟前
D. Storming Arasaka(Codeforces 2238)
c语言·开发语言·数据结构·c++·算法
W是笔名8 分钟前
python___容器类型的数据___列表
开发语言·windows·python
跨境数据猎手9 分钟前
多平台电商比价系统从零搭建合规
开发语言·爬虫·架构
hai31524754335 分钟前
九章编译法:DEEPSEEK V3.2汇编编译实例
java·开发语言
lkshop35 分钟前
Next.js 网站 SEO 优化:从 SSR、Sitemap 到结构化数据
开发语言·javascript·ecmascript
灯澜忆梦1 小时前
GO_函数_2
开发语言·golang·xcode
apihz2 小时前
经纬度制作高清卫星图片免费 API 接口详解
开发语言·ios·swift
娇气的红酒2 小时前
微软对PHP支持的改进,及其它一些胡言乱语
开发语言·microsoft·php
霸道流氓气质2 小时前
Harness Engineering 模块化指令实战:告别 600 行巨型 AGENTS.md
开发语言·人工智能·python
Traveler飞2 小时前
Ubuntu20.04 VMware 黑屏无法进入桌面,Ctrl+Alt+F2 可以进入终端,最终发现是磁盘空间满了
qt·ubuntu