Files
EJM_Display/PublicFunctions/CurvePlotWidget.cpp
2025-09-15 22:28:43 +08:00

126 lines
4.0 KiB
C++

#include "CurvePlotWidget.h"
#include <QVBoxLayout>
using namespace QtCharts; // 只在 cpp 里用,头文件里不要 using
// 放在 CurvePlotWidget.cpp 顶部
static void syncChartFontsAndColors(QChart *chart, const QWidget *host)
{
if (!chart || !host) return;
// 1. 坐标轴
for (auto *axis : chart->axes()) {
axis->setLabelsFont(host->font());
axis->setLabelsColor(host->palette().color(QPalette::WindowText));
axis->setTitleFont(host->font());
axis->setTitleBrush(QBrush(host->palette().color(QPalette::WindowText)));
}
// 2. 图例
if (auto *legend = chart->legend()) {
legend->setFont(host->font());
legend->setLabelColor(host->palette().color(QPalette::WindowText));
}
// 3. 标题(虽然已隐藏,也顺手同步)
chart->setTitleFont(host->font());
chart->setTitleBrush(QBrush(host->palette().color(QPalette::WindowText)));
}
CurvePlotWidget::CurvePlotWidget(QWidget *parent)
: QWidget(parent)
{
initChart();
}
void CurvePlotWidget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
if (e->type() == QEvent::FontChange || e->type() == QEvent::PaletteChange)
syncChartFontsAndColors(m_chart, this);
}
void CurvePlotWidget::initChart()
{
m_chart = new QChart;
m_chart->setTitle(""); // 无标题
m_chart->setMargins(QMargins(0,0,0,0)); // 关键:外框 0
m_chart->layout()->setContentsMargins(0,0,0,0);
m_chart->setBackgroundRoundness(0);
m_chart->setBackgroundVisible(false);
m_chart->legend()->setVisible(true); // 先隐藏图例,想显示时再 true
/* ---------- X 轴:当前时间 ---------- */
m_axisX = new QDateTimeAxis;
m_axisX->setFormat("hh:mm:ss"); // 时分秒
m_axisX->setTitleText(""); // 不显示轴标题
m_axisX->setLabelsVisible(true); // 不显示刻度数字
/* ---------- Y 轴 ---------- */
m_axisY = new QValueAxis;
m_axisY->setRange(-10, 10);
m_axisY->setTitleText(""); // 不显示轴标题
m_axisY->setLabelsVisible(true); // 不显示刻度数字
m_chart->addAxis(m_axisX, Qt::AlignBottom);
m_chart->addAxis(m_axisY, Qt::AlignLeft);
/* 3. 视图 */
m_view = new QChartView(m_chart);
m_view->setRenderHint(QPainter::Antialiasing);
m_view->setBackgroundBrush(Qt::NoBrush);
m_view->setFrameShape(QFrame::NoFrame);
m_view->setContentsMargins(0,0,0,0); // 视图本身无留白
/* 4. 布局 */
QVBoxLayout *lay = new QVBoxLayout(this);
lay->setContentsMargins(0,0,0,0); // 父布局无留白
lay->setSpacing(0); // 间距也 0
lay->addWidget(m_view);
}
int CurvePlotWidget::addSeries(const QString &name, const QColor &color)
{
QLineSeries *series = new QLineSeries;
series->setName(name);
series->setColor(color);
series->setUseOpenGL(true);
m_chart->addSeries(series);
series->attachAxis(m_axisX);
series->attachAxis(m_axisY);
m_series.append(series);
return m_series.size() - 1;
}
void CurvePlotWidget::appendPoint(int seriesIndex, double yValue)
{
if (seriesIndex < 0 || seriesIndex >= m_series.size())
return;
qint64 nowMs = QDateTime::currentMSecsSinceEpoch();
m_series[seriesIndex]->append(nowMs, yValue);
// if (m_series[seriesIndex]->count() > MAX_POINTS)
// m_series[seriesIndex]->remove(0);
updateAxisRange();
}
void CurvePlotWidget::updateAxisRange()
{
qreal minY = 1e9, maxY = -1e9;
for (QLineSeries *s : qAsConst(m_series)) {
const auto pts = s->pointsVector();
for (const QPointF &p : pts) {
minY = qMin(minY, p.y());
maxY = qMax(maxY, p.y());
}
}
if (minY == 1e9) minY = -10;
if (maxY == -1e9) maxY = 10;
m_axisY->setRange(minY - 1, maxY + 1);
/* X 轴:最近 TIME_WINDOW_S 秒 */
qint64 now = QDateTime::currentMSecsSinceEpoch();
m_axisX->setRange(QDateTime::fromMSecsSinceEpoch(now - TIME_WINDOW_S * 1000),
QDateTime::fromMSecsSinceEpoch(now));
}