通过MainWindow传递xaml中的实例myChart1 2 3到ChartManager进行初始化图表,然后通过SensorChartManager中实时通过时间发布发哦ChartManager中
This commit is contained in:
parent
b802f2e89b
commit
48f2e586e8
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Chart 管理器 - 负责图表初始化和实时更新
|
||||
/// </summary>
|
||||
public class ChartManager
|
||||
{
|
||||
private readonly Dispatcher dispatcher;
|
||||
|
|
@ -17,89 +15,185 @@ namespace WpfApp.Services
|
|||
private readonly DatabaseService db;
|
||||
private readonly EventService<GeneralEventArgs> 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<double> StandardMin = new ChartValues<double>();
|
||||
public ChartValues<double> StandardAvg = new ChartValues<double>();
|
||||
public ChartValues<double> StandardMax = new ChartValues<double>();
|
||||
public List<string> Labels = new List<string>();
|
||||
}
|
||||
|
||||
// 管理多个图表
|
||||
private Dictionary<CartesianChart, ChartData> charts = new Dictionary<CartesianChart, ChartData>();
|
||||
|
||||
public ChartManager(Dispatcher uiDispatcher,
|
||||
LogService logService,
|
||||
DatabaseService databaseService,
|
||||
EventService<GeneralEventArgs> eventService)
|
||||
{
|
||||
dispatcher = uiDispatcher;
|
||||
}
|
||||
public ChartManager(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
|
||||
{
|
||||
log = logService;
|
||||
db = databaseService;
|
||||
even = eventService;
|
||||
|
||||
SubscribeToSensorDataEvents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化图表
|
||||
/// 初始化图表(一次性设置标准线和柱状图)
|
||||
/// </summary>
|
||||
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<double> { 20, 10, 12, 5, 9 },
|
||||
Labels = labels.ToList(),
|
||||
LineConfigs = new List<LineConfig>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态更新图表数据(线程安全)
|
||||
/// </summary>
|
||||
public void UpdateChart(CartesianChart chart, List<double> columnData, List<LineConfig> 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<double>()
|
||||
};
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟后台数据采集并实时刷新图表
|
||||
/// 接收到传感器实时数据(单点更新)
|
||||
/// </summary>
|
||||
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<LineConfig>
|
||||
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<double> { 10, 10, 10, 10, 10 }, Stroke = Brushes.Blue },
|
||||
new LineConfig { Title = "标准2", Values = new List<double> { 20, 20, 20, 20, 20 }, Stroke = Brushes.Green },
|
||||
new LineConfig { Title = "标准3", Values = new List<double> { 30, 30, 30, 30, 30 }, Stroke = Brushes.Yellow }
|
||||
};
|
||||
|
||||
// 更新图表(通过 Dispatcher 保证线程安全)
|
||||
UpdateChart(chart, columnData, lineData);
|
||||
|
||||
await Task.Delay(6000); // 每秒更新一次
|
||||
UpdateChartPoint(chart, timeLabel, value);
|
||||
break;
|
||||
}
|
||||
}, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 更新单个图表的数据点(柱状图 + 标准线 + X轴标签)
|
||||
/// </summary>
|
||||
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<string>(data.Labels);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动添加数据到指定图表
|
||||
/// </summary>
|
||||
public void AddData(CartesianChart chart, double value, string label)
|
||||
{
|
||||
UpdateChartPoint(chart, label, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动清除指定图表的数据
|
||||
/// </summary>
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有图表
|
||||
/// </summary>
|
||||
public void ClearAllCharts()
|
||||
{
|
||||
foreach (var chart in charts.Keys)
|
||||
{
|
||||
ClearChart(chart);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 订阅传感器数据事件
|
||||
/// </summary>
|
||||
private void SubscribeToSensorDataEvents()
|
||||
{
|
||||
even?.AddEventHandler(SENSOR_DATA_EVENT, OnSensorDataReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,18 +16,18 @@ namespace WpfApp.Services
|
|||
private readonly DatabaseService db;
|
||||
private readonly EventService<GeneralEventArgs> 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<GeneralEventArgs> eventService)
|
||||
{
|
||||
dispatcherOwner = owner;
|
||||
}
|
||||
public SensorChartManager(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布传感器数据事件
|
||||
/// </summary>
|
||||
/// <param name="sensorTitle">传感器标题</param>
|
||||
/// <param name="sensorValue">传感器值</param>
|
||||
/// <param name="chartTitle">图表标题</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
39
Services/SensorDataEventArgs.cs
Normal file
39
Services/SensorDataEventArgs.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using guoke;
|
||||
|
||||
namespace WpfApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 传感器数据事件参数类,用于传递传感器的实时数据
|
||||
/// </summary>
|
||||
public class SensorDataEventArgs : GeneralEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 传感器标题/名称
|
||||
/// </summary>
|
||||
public string SensorTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传感器实时值
|
||||
/// </summary>
|
||||
public double SensorValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图表标题,用于区分不同的图表
|
||||
/// </summary>
|
||||
public string ChartTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化传感器数据事件参数
|
||||
/// </summary>
|
||||
/// <param name="sensorTitle">传感器标题</param>
|
||||
/// <param name="sensorValue">传感器实时值</param>
|
||||
/// <param name="chartTitle">图表标题</param>
|
||||
public SensorDataEventArgs(string sensorTitle, double sensorValue, string chartTitle)
|
||||
: base($"传感器数据更新: {sensorTitle}", sensorValue)
|
||||
{
|
||||
SensorTitle = sensorTitle;
|
||||
SensorValue = sensorValue;
|
||||
ChartTitle = chartTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user