Files
FullAutoWaterCheck/全自动水压检测仪/ChartManager.cs
2026-02-04 17:21:52 +08:00

275 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using OxyPlot.WindowsForms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace
{
/// <summary>
/// 图表管理器 - 负责实时曲线图的创建和数据更新
/// 第一Y轴实时压力地址3130
/// 第二Y轴压力设定值地址2400对应"压力设置(PSI)"
/// </summary>
public class ChartManager
{
private PlotView _plotView;
private PlotModel _plotModel;
private LineSeries _pressureSeries; // 实时压力值地址3130
private LineSeries _pressureSetSeries; // 压力设定值地址2400
private List<DataPoint> _pressureData;
private List<DataPoint> _pressureSetData;
private const int MAX_DATA_POINTS = 60; // 最多显示60个数据点
/// <summary>
/// 初始化图表并添加到指定面板
/// </summary>
public void InitializeChart(Control targetPanel)
{
targetPanel.Invoke(new Action(() =>
{
if (targetPanel == null)
throw new ArgumentNullException(nameof(targetPanel));
// 清除占位文字
targetPanel.Text = null;
// 初始化数据集合
_pressureData = new List<DataPoint>();
_pressureSetData = new List<DataPoint>();
// 创建PlotModel
_plotModel = new PlotModel
{
Title = "",
Background = OxyColors.White,
PlotAreaBorderColor = OxyColors.Gray
};
// 配置图例
_plotModel.Legends.Add(new OxyPlot.Legends.Legend
{
LegendPosition = OxyPlot.Legends.LegendPosition.TopCenter,
LegendOrientation = OxyPlot.Legends.LegendOrientation.Horizontal
});
// 配置X轴时间轴 - 使用测试时间总秒数)
var xAxis = new LinearAxis
{
Position = AxisPosition.Bottom,
Title = "测试时间",
TitleFontSize = 12,
FontSize = 10,
MajorGridlineStyle = LineStyle.Solid,
MajorGridlineColor = OxyColor.FromRgb(230, 230, 230),
MinorGridlineStyle = LineStyle.Dot,
MinorGridlineColor = OxyColor.FromRgb(240, 240, 240),
Minimum = 0,
Maximum = 60,
// 格式化X轴标签为HH:MM:SS格式
LabelFormatter = value =>
{
int totalSec = (int)value;
int h = totalSec / 3600;
int m = (totalSec % 3600) / 60;
int s = totalSec % 60;
return $"{h:D2}:{m:D2}:{s:D2}";
}
};
_plotModel.Axes.Add(xAxis);
// 配置左Y轴实时压力
var yAxisLeft = new LinearAxis
{
Position = AxisPosition.Left,
Title = "压力 (PSI)",
TitleFontSize = 12,
FontSize = 10,
TitleColor = OxyColors.Blue,
TextColor = OxyColors.Blue,
MajorGridlineStyle = LineStyle.Solid,
MajorGridlineColor = OxyColor.FromRgb(230, 230, 230),
MinorGridlineStyle = LineStyle.Dot,
MinorGridlineColor = OxyColor.FromRgb(240, 240, 240),
StringFormat = "F2",
Minimum = 0,
Key = "LeftAxis"
};
_plotModel.Axes.Add(yAxisLeft);
// 配置右Y轴压力设定值
var yAxisRight = new LinearAxis
{
Position = AxisPosition.Right,
Title = "压力设定值 (PSI)",
TitleFontSize = 12,
FontSize = 10,
TitleColor = OxyColors.Red,
TextColor = OxyColors.Red,
MajorGridlineStyle = LineStyle.None,
StringFormat = "F2",
Minimum = 0,
Key = "RightAxis"
};
_plotModel.Axes.Add(yAxisRight);
// 添加实时压力曲线
_pressureSeries = new LineSeries
{
Title = "实时压力",
Color = OxyColors.Blue,
StrokeThickness = 2,
MarkerType = MarkerType.Circle,
MarkerSize = 4,
MarkerFill = OxyColors.Blue,
YAxisKey = "LeftAxis"
};
_plotModel.Series.Add(_pressureSeries);
// 添加压力设定值曲线
_pressureSetSeries = new LineSeries
{
Title = "压力设定值",
Color = OxyColors.Red,
StrokeThickness = 2,
MarkerType = MarkerType.Diamond,
MarkerSize = 4,
MarkerFill = OxyColors.Red,
YAxisKey = "RightAxis"
};
_plotModel.Series.Add(_pressureSetSeries);
// 创建PlotView控件
_plotView = new PlotView
{
Model = _plotModel,
Dock = DockStyle.Fill,
BackColor = System.Drawing.Color.White
};
// 添加到目标面板
targetPanel.Controls.Add(_plotView);
}
/// <summary>
/// 添加新的数据点
/// </summary>
/// <param name="pressure">实时压力值</param>
/// <param name="pressureSetValue">压力设定值(来自"压力设置(PSI)"地址2400</param>
/// <param name="totalSeconds">测试时间(总秒数)</param>
public void AddDataPoint(double pressure, double pressureSetValue, int totalSeconds)
{
if (_pressureSeries == null || _pressureSetSeries == null || _plotModel == null)
return;
// 添加数据点使用测试时间总秒数作为X轴值
_pressureData.Add(new DataPoint(totalSeconds, pressure));
_pressureSetData.Add(new DataPoint(totalSeconds, pressureSetValue));
// 限制数据点数量,保持图表流畅
if (_pressureData.Count > MAX_DATA_POINTS)
{
_pressureData.RemoveAt(0);
_pressureSetData.RemoveAt(0);
}
// 更新系列数据
_pressureSeries.Points.Clear();
_pressureSeries.Points.AddRange(_pressureData);
_pressureSetSeries.Points.Clear();
_pressureSetSeries.Points.AddRange(_pressureSetData);
// 动态调整X轴范围
if (_pressureData.Count > 0)
{
var xAxis = _plotModel.Axes.FirstOrDefault(a => a.Position == AxisPosition.Bottom);
if (xAxis != null)
{
double minX = _pressureData.Min(p => p.X);
double maxX = _pressureData.Max(p => p.X);
xAxis.Minimum = minX;
xAxis.Maximum = maxX + 5; // 留一点余量
}
}
// 刷新图表
_plotModel.InvalidatePlot(true);
}
/// <summary>
/// 清除所有数据
/// </summary>
public void ClearData()
{
_pressureData?.Clear();
_pressureSetData?.Clear();
if (_pressureSeries != null)
{
_pressureSeries.Points.Clear();
}
if (_pressureSetSeries != null)
{
_pressureSetSeries.Points.Clear();
}
// 重置X轴范围
var xAxis = _plotModel?.Axes.FirstOrDefault(a => a.Position == AxisPosition.Bottom);
if (xAxis != null)
{
xAxis.Minimum = 0;
xAxis.Maximum = 60;
}
_plotModel?.InvalidatePlot(true);
}
/// <summary>
/// 更新图表配置(例如切换温度模式时)
/// </summary>
/// <param name="isHighTemperatureMode">是否为高温模式</param>
public void UpdateChartMode(bool isHighTemperatureMode)
{
if (_plotModel == null || _plotModel.Series.Count < 2)
return;
// 压力设定值曲线标题保持不变
if (_pressureSetSeries != null)
{
_pressureSetSeries.Title = "压力设定值";
}
// 可以根据模式调整Y轴范围压力设定值范围
foreach (var axis in _plotModel.Axes)
{
if (axis.Key == "RightAxis")
{
axis.Maximum = 10; // 压力设定值通常不超过10MPa
break;
}
}
_plotModel.InvalidatePlot(true);
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
_plotView?.Dispose();
_plotModel = null;
_pressureSeries = null;
_pressureSetSeries = null;
_pressureData = null;
_pressureSetData = null;
}
}
}