From 48f2e586e849e50989584939e9d21e0c566cb49a Mon Sep 17 00:00:00 2001 From: YONGYE Date: Tue, 14 Oct 2025 11:08:00 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E8=BF=87MainWindow=E4=BC=A0=E9=80=92x?= =?UTF-8?q?aml=E4=B8=AD=E7=9A=84=E5=AE=9E=E4=BE=8BmyChart1=202=203?= =?UTF-8?q?=E5=88=B0ChartManager=E8=BF=9B=E8=A1=8C=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E5=9B=BE=E8=A1=A8=EF=BC=8C=E7=84=B6=E5=90=8E=E9=80=9A?= =?UTF-8?q?=E8=BF=87SensorChartManager=E4=B8=AD=E5=AE=9E=E6=97=B6=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E6=97=B6=E9=97=B4=E5=8F=91=E5=B8=83=E5=8F=91=E5=93=A6?= =?UTF-8?q?ChartManager=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MainWindow.xaml.cs | 15 ++- Services/ChartManager.cs | 220 +++++++++++++++++++++++--------- Services/SensorChartManager.cs | 30 ++++- Services/SensorDataEventArgs.cs | 39 ++++++ 4 files changed, 228 insertions(+), 76 deletions(-) create mode 100644 Services/SensorDataEventArgs.cs diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index d7d9507..a15c713 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -32,7 +32,7 @@ public partial class MainWindow : Window db = databaseService; even = eventService; menu = new MenuController(this);// 初始化菜单控制器 - sensorManager = new SensorChartManager(this) + sensorManager = new SensorChartManager(this, log, db, even) { Sensor1 = Sensor1, Sensor2 = Sensor2, @@ -51,13 +51,11 @@ public partial class MainWindow : Window WindowHelper.SetWindowTitle(this, "FMSDGAUGE"); // 设置标题 - chartManager = new ChartManager(Dispatcher); - chartManager.InitCharts(myChart1, myChart2, myChart3); // 初始化图表 + chartManager = new ChartManager(Dispatcher, log, db, even); + chartManager.InitChart(myChart1); + chartManager.InitChart(myChart2); + chartManager.InitChart(myChart3); - // 启动实时数据刷新 - chartManager.StartAutoUpdate(myChart1, chartCts.Token, "myChart1"); - chartManager.StartAutoUpdate(myChart2, chartCts.Token, "myChart2"); - chartManager.StartAutoUpdate(myChart3, chartCts.Token, "myChart3"); } @@ -93,6 +91,8 @@ public partial class MainWindow : Window { // 开始检测 sensorManager.Start(); + //chartManager.Start(); // 启动图表刷新 + //chartManager.Clear(); BtnSensorControl.Content = "检测确定"; isDetecting = true; } @@ -100,6 +100,7 @@ public partial class MainWindow : Window { // 停止检测 sensorManager.Stop(); + //chartManager.Stop(); // 停止图表刷新 BtnSensorControl.Content = "检测开始"; isDetecting = false; } diff --git a/Services/ChartManager.cs b/Services/ChartManager.cs index c0db544..8769a4e 100644 --- a/Services/ChartManager.cs +++ b/Services/ChartManager.cs @@ -1,15 +1,13 @@ using guoke; +using LiveCharts; using LiveCharts.Wpf; -using System.Windows.Media; +using System; +using System.Collections.Generic; using System.Windows.Threading; using WpfApp.src.config; -using WpfApp.Utils; namespace WpfApp.Services { - /// - /// Chart 管理器 - 负责图表初始化和实时更新 - /// public class ChartManager { private readonly Dispatcher dispatcher; @@ -17,89 +15,185 @@ namespace WpfApp.Services private readonly DatabaseService db; private readonly EventService even; - public ChartManager(Dispatcher uiDispatcher) + private const string SENSOR_DATA_EVENT = "SensorDataUpdate"; + + // 最大保留点数 + private const int MAX_POINTS = 20; + + // 每个图表的数据封装 + private class ChartData + { + public ColumnSeries ColumnSeries; + public ChartValues StandardMin = new ChartValues(); + public ChartValues StandardAvg = new ChartValues(); + public ChartValues StandardMax = new ChartValues(); + public List Labels = new List(); + } + + // 管理多个图表 + private Dictionary charts = new Dictionary(); + + public ChartManager(Dispatcher uiDispatcher, + LogService logService, + DatabaseService databaseService, + EventService eventService) { dispatcher = uiDispatcher; - } - public ChartManager(LogService logService, DatabaseService databaseService, EventService eventService) - { log = logService; db = databaseService; even = eventService; + + SubscribeToSensorDataEvents(); } /// - /// 初始化图表 + /// 初始化图表(一次性设置标准线和柱状图) /// - public void InitCharts(params CartesianChart[] charts) - { - var labels = new[] { "13:27 23", "13:27 45", "13:27 49", "13:27 50", "13:27 55" }; - - var config = new ChartConfig - { - ColumnData = new List { 20, 10, 12, 5, 9 }, - Labels = labels.ToList(), - LineConfigs = new List - { - new LineConfig { Title = "标准1", Values = Enumerable.Repeat(5.0,5).ToList(), Stroke = Brushes.Blue }, - new LineConfig { Title = "标准2", Values = Enumerable.Repeat(10.0,5).ToList(), Stroke = Brushes.Green }, - new LineConfig { Title = "标准3", Values = Enumerable.Repeat(30.0,5).ToList(), Stroke = Brushes.Red, Unit="A" } - } - }; - - foreach (var chart in charts) - { - InitChart.InitCartesianChart(chart, config); - } - } - - /// - /// 动态更新图表数据(线程安全) - /// - public void UpdateChart(CartesianChart chart, List columnData, List lineData) + public void InitChart(CartesianChart chart) { dispatcher.Invoke(() => { - var config = new ChartConfig + if (chart == null) return; + + // 如果已经初始化过,先清除 + if (charts.ContainsKey(chart)) { - ColumnData = columnData, - Labels = chart.AxisX[0].Labels.ToList(), - LineConfigs = lineData + charts.Remove(chart); + } + + var data = new ChartData(); + data.ColumnSeries = new ColumnSeries + { + Title = "实时值", + Values = new ChartValues() }; - InitChart.InitCartesianChart(chart, config); + + var line1 = new LineSeries { Title = "标准下限", Values = data.StandardMin }; + var line2 = new LineSeries { Title = "标准均值", Values = data.StandardAvg }; + var line3 = new LineSeries { Title = "标准上限", Values = data.StandardMax }; + + chart.Series = new SeriesCollection { data.ColumnSeries, line1, line2, line3 }; + + chart.AxisX.Clear(); + chart.AxisY.Clear(); + + chart.AxisX.Add(new Axis + { + Title = "时间", + Labels = data.Labels + }); + + chart.AxisY.Add(new Axis + { + Title = "数值" + }); + + charts[chart] = data; }); } /// - /// 模拟后台数据采集并实时刷新图表 + /// 接收到传感器实时数据(单点更新) /// - public void StartAutoUpdate(CartesianChart chart, CancellationToken token) + private void OnSensorDataReceived(object sender, GeneralEventArgs e) { - Task.Run(async () => + if (e is SensorDataEventArgs sensorArgs) { - var rand = new Random(); + string chartTitle = sensorArgs.ChartTitle; // 例如 "myChart1" + double value = sensorArgs.SensorValue; + string timeLabel = DateTime.Now.ToString("HH:mm:ss"); - while (!token.IsCancellationRequested) + // 找到对应图表并更新 + foreach (var chart in charts.Keys) { - // 模拟采集数据 - var columnData = Enumerable.Range(0, 5).Select(_ => rand.NextDouble() * 50).ToList(); - // 这里实时获取从SensorChartManager中 - var lineData = new List + if (chart.Name == chartTitle) { - //new LineConfig { Title = "标准1", Values = Enumerable.Range(0,5).Select(_ => rand.NextDouble()*20).ToList(), Stroke = Brushes.Blue }, - //new LineConfig { Title = "标准2", Values = Enumerable.Range(0,5).Select(_ => rand.NextDouble()*30).ToList(), Stroke = Brushes.Green }, - //new LineConfig { Title = "标准3", Values = Enumerable.Range(0,5).Select(_ => rand.NextDouble()*40).ToList(), Stroke = Brushes.Yellow } - new LineConfig { Title = "标准1", Values = new List { 10, 10, 10, 10, 10 }, Stroke = Brushes.Blue }, - new LineConfig { Title = "标准2", Values = new List { 20, 20, 20, 20, 20 }, Stroke = Brushes.Green }, - new LineConfig { Title = "标准3", Values = new List { 30, 30, 30, 30, 30 }, Stroke = Brushes.Yellow } - }; - - // 更新图表(通过 Dispatcher 保证线程安全) - UpdateChart(chart, columnData, lineData); - - await Task.Delay(6000); // 每秒更新一次 + UpdateChartPoint(chart, timeLabel, value); + break; + } } - }, token); + } + } + + + /// + /// 更新单个图表的数据点(柱状图 + 标准线 + X轴标签) + /// + public void UpdateChartPoint(CartesianChart chart, string label, double value) + { + if (chart == null || !charts.TryGetValue(chart, out var data)) + return; + + dispatcher.Invoke(() => + { + // 保留四位小数 + double roundedValue = Math.Round(value, 4); + data.ColumnSeries.Values.Add(roundedValue); + // 对标准线固定值,强制 double + data.StandardMin.Add(Math.Round((double)5, 4)); + data.StandardAvg.Add(Math.Round((double)10, 4)); + data.StandardMax.Add(Math.Round((double)30, 4)); + data.Labels.Add(label); + + // 超过最大点数时,移除最旧的数据 + if (data.ColumnSeries.Values.Count > MAX_POINTS) + { + data.ColumnSeries.Values.RemoveAt(0); + data.StandardMin.RemoveAt(0); + data.StandardAvg.RemoveAt(0); + data.StandardMax.RemoveAt(0); + data.Labels.RemoveAt(0); + } + + // 刷新 X 轴标签 + chart.AxisX[0].Labels = new List(data.Labels); + }); + } + + /// + /// 手动添加数据到指定图表 + /// + public void AddData(CartesianChart chart, double value, string label) + { + UpdateChartPoint(chart, label, value); + } + + /// + /// 手动清除指定图表的数据 + /// + public void ClearChart(CartesianChart chart) + { + if (chart == null || !charts.TryGetValue(chart, out var data)) + return; + + dispatcher.Invoke(() => + { + data.ColumnSeries.Values.Clear(); + data.StandardMin.Clear(); + data.StandardAvg.Clear(); + data.StandardMax.Clear(); + data.Labels.Clear(); + chart.AxisX[0].Labels.Clear(); + }); + } + + /// + /// 清除所有图表 + /// + public void ClearAllCharts() + { + foreach (var chart in charts.Keys) + { + ClearChart(chart); + } + } + + /// + /// 订阅传感器数据事件 + /// + private void SubscribeToSensorDataEvents() + { + even?.AddEventHandler(SENSOR_DATA_EVENT, OnSensorDataReceived); } } } diff --git a/Services/SensorChartManager.cs b/Services/SensorChartManager.cs index 41118e5..baa4e0e 100644 --- a/Services/SensorChartManager.cs +++ b/Services/SensorChartManager.cs @@ -16,18 +16,18 @@ namespace WpfApp.Services private readonly DatabaseService db; private readonly EventService even; + // 事件名称常量 + private const string SENSOR_DATA_EVENT = "SensorDataUpdate"; + // 绑定的传感器控件 public SensorChart Sensor1 { get; set; } public SensorChart Sensor2 { get; set; } public SensorChart Sensor3 { get; set; } - public SensorChartManager(Window owner) + public SensorChartManager(Window owner, LogService logService, DatabaseService databaseService, EventService eventService) { dispatcherOwner = owner; - } - public SensorChartManager(LogService logService, DatabaseService databaseService, EventService eventService) - { log = logService; db = databaseService; even = eventService; @@ -58,8 +58,11 @@ namespace WpfApp.Services Sensor1.SetSensorData("传感器1", s1); Sensor2.SetSensorData("传感器2", s2); Sensor3.SetSensorData("传感器3", s3); - // 这里应当跨线程将传感器1 2 3的同时将实时值传递到ChartManger中 - + + // 通过事件将传感器数据传递到ChartManager + PublishSensorData("传感器1", s1, "myChart1"); + PublishSensorData("传感器2", s2, "myChart2"); + PublishSensorData("传感器3", s3, "myChart3"); }); await Task.Delay(1000); // 每1000毫秒采集一次 @@ -74,5 +77,20 @@ namespace WpfApp.Services { cts?.Cancel(); } + + /// + /// 发布传感器数据事件 + /// + /// 传感器标题 + /// 传感器值 + /// 图表标题 + private void PublishSensorData(string sensorTitle, double sensorValue, string chartTitle) + { + if (even != null) + { + var eventArgs = new SensorDataEventArgs(sensorTitle, sensorValue, chartTitle); + even.TriggerEvent(SENSOR_DATA_EVENT, this, eventArgs); + } + } } } diff --git a/Services/SensorDataEventArgs.cs b/Services/SensorDataEventArgs.cs new file mode 100644 index 0000000..b81df2b --- /dev/null +++ b/Services/SensorDataEventArgs.cs @@ -0,0 +1,39 @@ +using guoke; + +namespace WpfApp.Services +{ + /// + /// 传感器数据事件参数类,用于传递传感器的实时数据 + /// + public class SensorDataEventArgs : GeneralEventArgs + { + /// + /// 传感器标题/名称 + /// + public string SensorTitle { get; set; } + + /// + /// 传感器实时值 + /// + public double SensorValue { get; set; } + + /// + /// 图表标题,用于区分不同的图表 + /// + public string ChartTitle { get; set; } + + /// + /// 初始化传感器数据事件参数 + /// + /// 传感器标题 + /// 传感器实时值 + /// 图表标题 + public SensorDataEventArgs(string sensorTitle, double sensorValue, string chartTitle) + : base($"传感器数据更新: {sensorTitle}", sensorValue) + { + SensorTitle = sensorTitle; + SensorValue = sensorValue; + ChartTitle = chartTitle; + } + } +} \ No newline at end of file