qchart 绘图
效果图

CustomChartView.h/cpp
#pragma once
#include <QChartView>
#include <QtWidgets/QGraphicsRectItem>
#include <QtWidgets/QGraphicsTextItem>
#include <QtGui/QMouseEvent>
#include <qlineseries.h>
#include <qmath.h>
#include <qscatterseries.h>
#include <qdebug.h>
using namespace QtCharts;
class CustomChartView : public QChartView {
public:
explicit CustomChartView(QChart* chart, QWidget* parent = nullptr)
: QChartView(chart, parent), tooltipBox(nullptr), tooltipText(nullptr), hoverDistance(5) {}
protected:
void resizeEvent(QResizeEvent* event) override {
// 调用基类的resizeEvent以确保正常的大小调整行为
QChartView::resizeEvent(event);
// 更新图例的位置
if (chart()->legend()) {
QRectF plotAreaRect = chart()->plotArea();
chart()->legend()->setGeometry(QRectF(plotAreaRect.right() - 100,
plotAreaRect.top(),
100,
80));
}
}
void mouseMoveEvent(QMouseEvent* event) override {
QPointF point = chart()->mapToValue(event->pos());
bool foundPoint = false;
//考虑根据 <sqrt 1/4*dx^2 +1/4*dy^2 确定
qreal nearestDistance = hoverDistance;
foreach(QAbstractSeries * series, chart()->series()) {
if (auto Scatter = dynamic_cast<QScatterSeries*>(series)) {
for (const QPointF& dataPoint : Scatter->points()) {
qreal distance = qSqrt(qPow(point.x() - dataPoint.x(), 2) + qPow(point.y() - dataPoint.y(), 2));
if (distance <= nearestDistance) {
foundPoint = true;
showTooltip(dataPoint);
break;
}
}
if (foundPoint) break;
}
}
if (!foundPoint) {
hideTooltip();
}
QChartView::mouseMoveEvent(event);
}
private:
QGraphicsRectItem* tooltipBox;
QGraphicsTextItem* tooltipText;
int hoverDistance; // 鼠标悬停的有效距离
void showTooltip(const QPointF& point) {
QString text = QString("X: %1\nY: %2").arg(point.x()).arg(point.y());
if (!tooltipBox) {
tooltipBox = new QGraphicsRectItem;
tooltipBox->setBrush(QBrush(QColor(255, 255, 255))); // 白色背景
chart()->scene()->addItem(tooltipBox);
tooltipText = new QGraphicsTextItem;
chart()->scene()->addItem(tooltipText);
}
QFontMetrics metrics(tooltipText->font());
QRect boundingRect = metrics.boundingRect(text);
qDebug()<< "metrics.boundingRect(text);"<<metrics.boundingRect(text);
boundingRect = QRect(5, 5, 60, 40);
//boundingRect.setTopLeft(QPoint(20, 20));
tooltipBox->setRect(boundingRect);
QPointF position = chart()->mapToPosition(point);
tooltipBox->setPos(position + QPointF(30, -10)); // 调整位置以避免覆盖数据点
tooltipText->setPlainText(text);
tooltipText->setPos(position + QPointF(35, -10));
}
void hideTooltip() {
if (tooltipBox) {
chart()->scene()->removeItem(tooltipBox);
delete tooltipBox;
tooltipBox = nullptr;
}
if (tooltipText) {
chart()->scene()->removeItem(tooltipText);
delete tooltipText;
tooltipText = nullptr;
}
}
};
#include "CustomChartView.h"
//无
QtWidgetsApplication2.h/cpp
#pragma once
#include <QtWidgets/QWidget>
#include "ui_QtWidgetsApplication2.h"
struct PlotPos {
public:
PlotPos(double _x, double _y):x(_x),y(_y)
{
}
double x;
double y;
};
class QtWidgetsApplication2 : public QWidget
{
Q_OBJECT
public:
QtWidgetsApplication2(QWidget *parent = nullptr);
~QtWidgetsApplication2();
void init();
private:
Ui::QtWidgetsApplication2Class ui;
};
#include "QtWidgetsApplication2.h"
#include <QtCharts>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QSplineSeries>
#include <QLegend>
#include <qtimer.h>
#include "CustomChartView.h"
using namespace QtCharts;
QtWidgetsApplication2::QtWidgetsApplication2(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
init();
}
QtWidgetsApplication2::~QtWidgetsApplication2()
{}
void QtWidgetsApplication2::init()
{// 创建一个图表实例
QChart* chart = new QChart();
// 假设这是你的两个点集
std::vector<PlotPos> pointsSet1; // 示例数据,实际应从你的数据源填充
std::vector<PlotPos> pointsSet2;
for (int i = 1; i < 100; ++i)
{
pointsSet1.push_back(PlotPos(i,i));
pointsSet2.push_back(PlotPos(i, i+10));
}
QList<QPointF>list,list2;
list.reserve(pointsSet1.size());
for (auto& a : pointsSet1)
{
list.append(QPointF(a.x, a.y));
}
for (auto& b : pointsSet2)
{
list2.append(QPointF(b.x, b.y));
}
QLineSeries* serial = new QLineSeries(this);//必须要new, 才能实现更新
QScatterSeries* scatterSeries1 = new QScatterSeries(chart);
serial->setName("Line 1");//名称
serial->append(list);//在serial中添加数据
chart->addSeries(serial);//将数据加载到QChart中
scatterSeries1->append(list);
scatterSeries1->setMarkerSize(10); // 设置点的大小
chart->addSeries(scatterSeries1);
QLineSeries* serial2 = new QLineSeries(this);//必须要new, 才能实现更新
QScatterSeries* scatterSeries12 = new QScatterSeries(chart);
serial2->setName("Line 2");//名称
serial2->append(list2);//在serial中添加数据
chart->addSeries(serial2);//将数据加载到QChart中
scatterSeries12->append(list2);
scatterSeries12->setMarkerSize(10); // 设置点的大小
chart->addSeries(scatterSeries12);
chart->createDefaultAxes();//根据数据集,自动创建坐标轴,坐标轴的区间恰好完全容纳已有的数据集
chart->setTitle("chart");//chart名称
//chart->setAnimationOptions(QChart::SeriesAnimations);//以动画的形式显示
//chart->legend()->setAlignment(Qt::AlignRight);//(图例的位置)
//chart->legend()->setAlignment(Qt::AlignTop | Qt::AlignRight); // 设置图例对齐方式
chart->legend()->markers(scatterSeries1).first()->setVisible(false);//屏蔽散点图的图例
chart->legend()->markers(scatterSeries12).first()->setVisible(false);//屏蔽散点图的图例
//最后需要将chart交给QChartView
//QChartView* view = new QChartView(chart);//将chart进行显示
CustomChartView* view = new CustomChartView(chart);//将chart进行显示
view->setRenderHint(QPainter::Antialiasing);//消除锯齿
//view->setFixedSize(600, 600);//chart大小
chart->legend()->detachFromChart();
chart->legend()->setBackgroundVisible(true);
chart->legend()->setBrush(QBrush(QColor(128, 128, 128, 128)));
chart->legend()->setPen(QPen(QColor(192, 192, 192, 192)));
chart->legend()->setVisible(true);//图例显示
//chart->legend()->setGeometry(QRectF(chart->plotArea().right() - 100, chart->plotArea().top()+30, 50, 80));
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(view);
this->setLayout(layout);
//重写resize()事件
/*QTimer::singleShot(0, view, [chart]() {
qDebug() << "Plot Area:" << chart->plotArea();
chart->legend()->setGeometry(QRectF(chart->plotArea().right() - 100, chart->plotArea().top(), 100, 80));
});*/
//qDebug() << "plotArea" << view->plotArea();
}
main.cpp
#include "QtWidgetsApplication2.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtWidgetsApplication2 w;
w.show();
return a.exec();
}
浙公网安备 33010602011771号