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();
}
第一次写博客,我也是初学者,有问题欢迎讨论。谢谢。
链接: 源代码下载地址.