Qt QChart 选择区间、鼠标位置实时显示

本文介绍了如何使用Qt QChart实现选择数据区间及鼠标位置实时显示的功能。通过Qt Creator 4.3.1和Qt 5.9.0构建,程序展示了一个包含QChartMouseEvent类的示例,该类重写了QChartView的鼠标事件,并在事件完成后发送信号。主要涉及的文件包括QChartMouseEvent.h和.cpp,以及UI部分的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Qt QChart 选择区间、鼠标位置实时显示

效果图

在这里插入图片描述


程序

一、运行环境

Qt Creator 4.3.1
Based on Qt 5.9.0 (MSVC 2015, 32 bit)


二、程序目录结构

在这里插入图片描述

三、代码
  • QChartTest.pro

只加入了一段代码 QT += charts

#-------------------------------------------------
#
# Project created by QtCreator 2020-12-14T11:04:49
#
#-------------------------------------------------

QT       += charts

TARGET = QChartTest
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp \
    QChartMouseEvent.cpp

HEADERS += \
        mainwindow.h \
    QChartMouseEvent.h

FORMS += \
        mainwindow.ui

  • QChartMouseEvent.h
    该类继承QChartView,用于重构QChartView鼠标事件
#ifndef QCHARTMOUSEEVENT_H
#define QCHARTMOUSEEVENT_H

#include <QChartView>
#include <QMouseEvent>
#include <QGraphicsSimpleTextItem>
#include <QGestureEvent>

QT_CHARTS_USE_NAMESPACE

class QChartMouseEvent : public QChartView
{
    Q_OBJECT

public:
    QChartMouseEvent(QWidget* parent = nullptr);
    ~QChartMouseEvent();

signals:
    void mouseMoving(QPointF point);
    void mousePress(QPointF point);
    void mouseLeftRelease(QPointF point);
    void mouseRightRelease();
    void mouseLeave();

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void leaveEvent(QEvent* event);

private:
    bool m_isPress = false;
    double m_xMin, m_xMax, m_yMin, m_yMax = 0.0;
    QGraphicsSimpleTextItem* m_coordItem = NULL;
    QGraphicsSimpleTextItem* m_coordPointFront = NULL;
    QGraphicsSimpleTextItem* m_coordPointBack = NULL;
};

#endif  // QCHARTMOUSEEVENT_H

  • QChartMouseEvent.cpp
    重构鼠标事件,事件完成后发送信号给外部
#include "QChartMouseEvent.h"
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
#include <QValueAxis>
#include <QPainter>

QChartMouseEvent::QChartMouseEvent(QWidget* parent) : QChartView(parent) {}

QChartMouseEvent::~QChartMouseEvent() {}

void QChartMouseEvent::mousePressEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton) {
        m_isPress = true;
        this->setRubberBand(QChartView::RectangleRubberBand);
        QPointF curVal = this->chart()->mapToValue(event->pos());
        emit mousePress(curVal);

        if (!m_coordPointFront) {
            m_coordPointFront = new QGraphicsSimpleTextItem(this->chart());
            m_coordPointFront->setZValue(5);
            m_coordPointFront->show();
        }
        m_coordPointFront->setVisible(true);

        /// 获取纵轴
        QValueAxis* axisY = (QValueAxis*)chart()->axisY();
        QPointF curTemp = this->chart()->mapToPosition(QPointF(curVal.x(), axisY->max()));
        m_coordPointFront->setPos(curTemp.x(), curTemp.y());
        m_coordPointFront->setText(QString("X:%1").arg(curVal.x()));
    }
    QChartView::mousePressEvent(event);
}

void QChartMouseEvent::mouseMoveEvent(QMouseEvent* event)
{
    if (!m_coordItem) {
        m_coordItem = new QGraphicsSimpleTextItem(this->chart());
        m_coordItem->setZValue(5);
        m_coordItem->show();
    }
    m_coordItem->setVisible(true);
    const QPoint curPos = event->pos();
    QPointF curVal = this->chart()->mapToValue(curPos);
    QString coordStr = QString("X = %1\nY = %2").arg(curVal.x()).arg(curVal.y());
    m_coordItem->setText(coordStr);
    m_coordItem->setPos(curPos.x(), curPos.y() - 40);

    emit mouseMoving(curVal);

    QChartView::mouseMoveEvent(event);
}

void QChartMouseEvent::mouseReleaseEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton && m_isPress) {
        m_isPress = !m_isPress;
        QPointF curVal = this->chart()->mapToValue(event->pos());
        emit mouseLeftRelease(curVal);

        if (!m_coordPointBack) {
            m_coordPointBack = new QGraphicsSimpleTextItem(this->chart());
            m_coordPointBack->setZValue(5);
            m_coordPointBack->show();
        }
        m_coordPointBack->setVisible(true);

        /// 获取纵轴
        QValueAxis* axisY = (QValueAxis*)chart()->axisY();
        QPointF curTemp = this->chart()->mapToPosition(QPointF(curVal.x(), axisY->max()));
        m_coordPointBack->setPos(curTemp.x(), curTemp.y());
        m_coordPointBack->setText(QString("X:%1").arg(curVal.x()));
    }
    if (event->button() == Qt::RightButton) {
        emit mouseRightRelease();
        m_coordPointBack->setVisible(false);
        m_coordPointFront->setVisible(false);
    }
    this->setRubberBand(QChartView::NoRubberBand);
    QChartView::mouseReleaseEvent(event);
}

void QChartMouseEvent::leaveEvent(QEvent*)
{
    emit mouseLeave();
    m_coordItem->setVisible(false);
}

  • mainwindow.ui
    放置一个widget,并提升为“QChartMouseEvent”
    在这里插入图片描述

  • mainwindow.h
    声明槽,接收QChartMouseEvent信号

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

typedef QPair<QPointF, QString> Data;
typedef QList<Data> DataList;
typedef QList<DataList> DataTable;

#include <QChart>
#include <QChartView>
#include <QLineSeries>
QT_CHARTS_USE_NAMESPACE

namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget* parent = 0);
    ~MainWindow();

private:
    void initConnect();
    void initChart();
    QChart* createLineChart() const;
    DataTable generateRandomData(int listCount, int valueMax, int valueCount) const;

private slots:
    void onMouseMoving(QPointF point);
    void onMousePress(QPointF point);
    void onMouseLeftRelease(QPointF point);
    void onMouseRightRelease();
    void onMouseLeave();

private:
    Ui::MainWindow* ui;
    DataTable m_dataTable;
    QChart* chart = NULL;

    QLineSeries* serie_pointX = NULL;
    QLineSeries* serie_pointY = NULL;
    QLineSeries* section_front = NULL;
    QLineSeries* section_back = NULL;
};

#endif  // MAINWINDOW_H

  • mainwindow.cpp
    generateRandomData 生成随机数据
    createLineChart 生成图表
    其他为槽函数、初始化函数
#include <QTime>

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //    this->setMouseTracking(true);
    initConnect();
    initChart();

    m_dataTable = generateRandomData(3, 20, 10);
    ui->chartWidget->setChart(createLineChart());
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initConnect()
{
    connect(ui->chartWidget, &QChartMouseEvent::mouseMoving, this, &MainWindow::onMouseMoving);
    connect(ui->chartWidget, &QChartMouseEvent::mousePress, this, &MainWindow::onMousePress);
    connect(ui->chartWidget, &QChartMouseEvent::mouseLeftRelease, this, &MainWindow::onMouseLeftRelease);
    connect(ui->chartWidget, &QChartMouseEvent::mouseRightRelease, this, &MainWindow::onMouseRightRelease);
    connect(ui->chartWidget, &QChartMouseEvent::mouseLeave, this, &MainWindow::onMouseLeave);
}

void MainWindow::initChart()
{
    chart = new QChart();
    serie_pointX = new QLineSeries(chart);
    serie_pointY = new QLineSeries(chart);
    section_front = new QLineSeries(chart);
    section_back = new QLineSeries(chart);

    serie_pointX->setName("Point X");
    serie_pointY->setName("Point Y");
    section_front->setName("Section Front");
    section_back->setName("Section Back");

    serie_pointX->setVisible(false);
    serie_pointY->setVisible(false);
    section_front->setVisible(false);
    section_back->setVisible(false);

    section_front->setPen(QPen(Qt::DashLine));
    section_back->setPen(QPen(Qt::DashLine));

    chart->addSeries(serie_pointX);
    chart->addSeries(serie_pointY);
    chart->addSeries(section_front);
    chart->addSeries(section_back);
}

QChart* MainWindow::createLineChart() const
{
    chart->setTitle("Line chart");
    QString name("Series ");
    int nameIndex = 0;
    foreach (DataList list, m_dataTable) {
        QLineSeries* series = new QLineSeries(chart);
        foreach (Data data, list)
            series->append(data.first);
        series->setName(name + QString::number(nameIndex));
        nameIndex++;
        chart->addSeries(series);
    }
    chart->createDefaultAxes();

    return chart;
}

DataTable MainWindow::generateRandomData(int listCount, int valueMax, int valueCount) const
{
    DataTable dataTable;

    // set seed for random stuff
    qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));

    // generate random data
    for (int i(0); i < listCount; i++) {
        DataList dataList;
        qreal yValue(0);
        for (int j(0); j < valueCount; j++) {
            yValue = yValue + (qreal)(qrand() % valueMax) / (qreal)valueCount;
            QPointF value((j + (qreal)rand() / (qreal)RAND_MAX) * ((qreal)valueMax / (qreal)valueCount), yValue);
            QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
            dataList << Data(value, label);
        }
        dataTable << dataList;
    }

    return dataTable;
}

void MainWindow::onMouseMoving(QPointF point)
{
    serie_pointX->clear();
    serie_pointY->clear();
    serie_pointX->setVisible(true);
    serie_pointY->setVisible(true);

    serie_pointX->append(QPointF(0, point.y()));
    serie_pointX->append(QPointF(chart->maximumWidth(), point.y()));
    serie_pointY->append(QPointF(point.x(), 0));
    serie_pointY->append(QPointF(point.x(), chart->maximumHeight()));
}

void MainWindow::onMousePress(QPointF point)
{
    section_front->clear();
    section_front->setVisible(true);

    section_front->append(point.x(), 0);
    section_front->append(point.x(), chart->maximumHeight());
}

void MainWindow::onMouseLeftRelease(QPointF point)
{
    section_back->clear();
    section_back->setVisible(true);

    section_back->append(point.x(), 0);
    section_back->append(point.x(), chart->maximumHeight());
}

void MainWindow::onMouseRightRelease()
{
    section_front->setVisible(false);
    section_back->setVisible(false);
}

void MainWindow::onMouseLeave()
{
    serie_pointX->setVisible(false);
    serie_pointY->setVisible(false);
}

  • main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.resize(1000, 700);
    w.show();

    return a.exec();
}


第一次写博客,我也是初学者,有问题欢迎讨论。谢谢。

链接: 源代码下载地址.

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhigen.li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值