關於使用 SciChart 如何製作多 Channel 示波器顯示。
主要功能拆解:
- 多個 Channel 顯示波形 (圖中以三角函數縮放作為範例)
- 滑鼠移動後,同時顯示 Legend
- 圈選範圍後,可以放大分析
- 按空白鍵後復位分析
- 局部開啟 Channel 開關
詳情專案可以見程式碼: https://github.com/hpcslag/SciChart-MultiChannel
單個 Channel 的功能性實作
從最簡單的開始,用 Sci-Chart Examples 就能做,找出 Chart_SplineScatterLineChart 範本,改成以下 wpf:
<UserControl x:Class="SciChart.Examples.Examples.CreateACustomChart.SplineLineSeries.MainChart" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="http://schemas.abtsoftware.co.uk/scichart" xmlns:ext="http://schemas.abtsoftware.co.uk/scichart/exampleExternals" Loaded="ChartLoaded" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="400" d:DesignWidth="600" mc:Ignorable="d"> <!--注意引入哪些 xmlns:[class] --> <UserControl.Resources> <!-- 這是滑鼠移動上去 Chart 內容的 WPF Style 定義 The style for the rollover line --> <Style x:Key="RolloverLineStyle" TargetType="Line"> <Setter Property="Stroke" Value="White"/> <Setter Property="StrokeThickness" Value="1"/> <Setter Property="IsHitTestVisible" Value="False"/> <Setter Property="UseLayoutRounding" Value="True"/> </Style> <!-- 這是工具列的 Component Data Template, A1 Tooltip Style Format --> <DataTemplate x:Key="XyTooltipTemplate" DataType="s:XySeriesInfo"> <StackPanel Orientation="Vertical"> <TextBlock Foreground="White"> <Run Text="Series: "/> <Run Text="{Binding SeriesName, StringFormat='{}{0}'}"/> </TextBlock> <TextBlock Foreground="White"> <Run Text="X-Axis: "/> <Run Text="{Binding XValue, StringFormat=X: \{0:0.000000\}}"/> </TextBlock> <TextBlock Foreground="White"> <Run Text="Y-Axis: "/> <Run Text="{Binding YValue, StringFormat=Y: \{0:0.0000000\}}"/> </TextBlock> </StackPanel> </DataTemplate> <!-- Label 顯示的樣式 --> <Style x:Key="RightAlignedLabelStyle" TargetType="s:DefaultTickLabel"> <Setter Property="HorizontalAnchorPoint" Value="Right" /> </Style> <!-- Y 軸呈現的樣式 --> <Style x:Key="YAxisStyle" TargetType="s:AxisBase"> <Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="VisibleRange" Value="-2, 2" /> <Setter Property="VisibleRangeLimit" Value="-2, 2" /> <Setter Property="AutoRange" Value="Never" /> <Setter Property="AxisAlignment" Value="Left" /> <Setter Property="DrawMinorGridLines" Value="False" /> <Setter Property="DrawMinorTicks" Value="False" /> <Setter Property="DrawMajorGridLines" Value="False" /> <Setter Property="DrawMajorBands" Value="False" /> <Setter Property="TickLabelStyle" Value="{StaticResource RightAlignedLabelStyle}" /> </Style> <!-- Y 軸 Pannel , 基本上要在這邊定義有多少 Items(Channel 數),用來決定版面高度 --> <!-- Optionally replace the default StackPanel for the Axis Container. In this example we create a Grid --> <!-- with 4x rows and one column. Then use Grid.Row on the actual Axis instances to place in the correct rows --> <!-- --> <!-- By Default SciChart will place YAxes stacked horizontally, but using this feature we can override --> <!-- to place vertically on the same chart surface --> <ItemsPanelTemplate x:Key="YAxesPanel"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="10" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> </Grid> </ItemsPanelTemplate> <!-- 筆刷樣式 --> <LinearGradientBrush x:Key="MountainFillBrush" StartPoint="0,0" EndPoint="0,1"> <GradientStop Offset="0" Color="#A83376E5" /> <GradientStop Offset="1" Color="#333376E5" /> </LinearGradientBrush> </UserControl.Resources> <Grid> <!-- 建立 charts 了 --> <!-- Create the chart surface --> <s:SciChartSurface x:Name="sciChart" LeftAxesPanelTemplate="{StaticResource YAxesPanel}" RightAxesPanelTemplate="{StaticResource YAxesPanel}"> <s:SciChartSurface.Annotations> <s:TextAnnotation Name="chartTitle" Text="數位訊號波型控制" HorizontalAnchorPoint="Center" VerticalAnchorPoint="Top" X1="0.5" Y1="0.01" CoordinateMode="Relative"/> </s:SciChartSurface.Annotations> <!-- 這裡面是要定義哪些 Y 軸 ID (就是哪個 channel) 要套用到哪個種類的 Series(波) Render 方法--> <!-- Declare RenderableSeries --> <s:SciChartSurface.RenderableSeries> <!-- A1 s:RolloverModifier.TooltipTemplate -> Set Tooltip Style --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch0" /> </s:SciChartSurface.RenderableSeries> <!-- X 軸只呈現數字 --> <!-- Create an X Axis with Growby --> <s:SciChartSurface.XAxis> <s:NumericAxis /> </s:SciChartSurface.XAxis> <!-- 定義數值,綁定到哪一條 Series --> <!-- Create a Y Axis with Grid.Row to position on the YAxis Panel. Alternate axis display MajorGridLines --> <s:SciChartSurface.YAxes> <s:NumericAxis x:Name="Ch0" Grid.Row="0" AxisTitle="Ch0" Id="Ch0" Style="{StaticResource YAxisStyle}" /> </s:SciChartSurface.YAxes> <!-- 定義工具 bar: 基本上套用上面定義過的樣式(像是 RolloverLineStyle) --> <s:SciChartSurface.ChartModifier> <s:ModifierGroup> <s:RubberBandXyZoomModifier IsXAxisOnly="True" /> <s:ZoomExtentsModifier /> <s:CursorModifier ShowAxisLabels="False" ShowTooltip="False" /> <s:LegendModifier ShowLegend="True" LegendPlacement="Inside" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Right"/> <s:RolloverModifier x:Name="RolloverModifier" ShowAxisLabels="True" UseInterpolation="True" LineOverlayStyle="{StaticResource RolloverLineStyle}" ShowTooltipOn="Always"/> <s:XAxisDragModifier/> <s:YAxisDragModifier/> </s:ModifierGroup> </s:SciChartSurface.ChartModifier> </s:SciChartSurface> </Grid> </UserControl>
單個 Channel 是這麼顯示的,他的 C# 是:
// ************************************************************************************* // SCICHART® Copyright SciChart Ltd. 2011-2018. All rights reserved. // // Web: http://www.scichart.com // Support: [email protected] // Sales: [email protected] // // SplineChartExampleView.xaml.cs is part of the SCICHART® Examples. Permission is hereby granted // to modify, create derivative works, distribute and publish any part of this source // code whether for commercial, private or personal use. // // The SCICHART® examples are distributed in the hope that they will be useful, but // without any warranty. It is provided "AS IS" without warranty of any kind, either // expressed or implied. // ************************************************************************************* using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using SciChart.Charting.Model.DataSeries; using SciChart.Examples.ExternalDependencies.Data; namespace SciChart.Examples.Examples.CreateACustomChart.SplineLineSeries { /// <summary> /// Interaction logic for CustomChartExampleView.xaml /// </summary> public partial class MainChart : UserControl { public MainChart() { InitializeComponent(); //按下 Space 之後,回到波形 Overview this.KeyDown += (object sender, KeyEventArgs e) => { if(e.Key == Key.Space) { this.sciChart.ZoomExtents(); } }; } //先定義好有幾個 channel public int channel_length = 1; private void ChartLoaded(object sender, RoutedEventArgs e) { chartTitle.Text = "波型圖標題"; Task.Factory.StartNew(() => { // Creates `N` dataseries with data on a background thread var dataSeries = new List<IDataSeries>(); for (int i = 0; i < channel_length; i++) { var ds = new XyDataSeries<double, double>() { SeriesName="CH "+i }; dataSeries.Add(ds); var someData = DataManager.Instance.GetSinewave(i+1.0, 0.0, 1000, 4); //隨機分配正弦波,做 i+1 伸縮 ds.Append(someData.XData, someData.YData); } // Creates `N` renderable series on the UI thread Dispatcher.BeginInvoke(new Action(() => CreateRenderableSeries(dataSeries))); }); sciChart.ZoomExtents(); } public static void addData(DoubleSeries data, double x, double y) { XYPoint xy = new XYPoint(); xy.X = x; xy.Y = y; data.Add(xy); } private void CreateRenderableSeries(List<IDataSeries> result) { // Batch updates with one redraw using (sciChart.SuspendUpdates()) { for (int i = 0; i < channel_length; i++) { sciChart.RenderableSeries[i].DataSeries = result[i]; } } } } }
現在,圖表已經可以單軸顯示了:
多個 Channel 的功能性實作
多個 Channel, wpf 中需要對 y 軸 grid 增加定義,然後增加 render series 數量以及 channel 數值綁定。 (這三件事)
由於程式碼過多,以下只呈現部分結構,可透過文字搜尋找到,進行更改
<!-- Optionally replace the default StackPanel for the Axis Container. In this example we create a Grid --> <!-- with 4x rows and one column. Then use Grid.Row on the actual Axis instances to place in the correct rows --> <!-- --> <!-- By Default SciChart will place YAxes stacked horizontally, but using this feature we can override --> <!-- to place vertically on the same chart surface --> <ItemsPanelTemplate x:Key="YAxesPanel"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <!-- 第 1 個 channel --> <RowDefinition Height="10" /> <!-- Height 間隔 --> <RowDefinition Height="*" /> <!-- 第 2 個 channel --> <RowDefinition Height="10" /> <RowDefinition Height="*" /> <!-- 第 3 個 channel --> <RowDefinition Height="10" /> <RowDefinition Height="*" /> <!-- 第 4 個 channel --> <RowDefinition Height="10" /> <RowDefinition Height="*" /> <!-- 第 5 個 channel --> <RowDefinition Height="10" /> <RowDefinition Height="*" /> <!-- 第 6 個 channel --> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> </Grid> </ItemsPanelTemplate>
以及
<!-- Declare RenderableSeries --> <s:SciChartSurface.RenderableSeries> <!-- A1 s:RolloverModifier.TooltipTemplate -> Set Tooltip Style --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch0" /> <!-- 第 1 個 channel series render --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch1" /> <!-- 第 2 個 channel series render --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch2" /> <!-- 第 3 個 channel series render --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch3" /> <!-- 第 4 個 channel series render --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch4" /> <!-- 第 5 個 channel series render --> <s:FastLineRenderableSeries s:RolloverModifier.TooltipTemplate="{StaticResource XyTooltipTemplate}" Stroke="#30b7ff" YAxisId="Ch5" /> <!-- 第 6 個 channel series render --> </s:SciChartSurface.RenderableSeries>
以及
<!-- Create a Y Axis with Grid.Row to position on the YAxis Panel. Alternate axis display MajorGridLines --> <s:SciChartSurface.YAxes> <s:NumericAxis x:Name="Ch0" Grid.Row="0" AxisTitle="Ch0" Id="Ch0" Style="{StaticResource YAxisStyle}" /> <!-- 第 1 個 channel 數值綁定 --> <s:NumericAxis x:Name="Ch1" Grid.Row="2" AxisTitle="Ch1" Id="Ch1" Style="{StaticResource YAxisStyle}" /> <!-- 第 2 個 channel 數值綁定 -->
<s:NumericAxis x:Name="Ch2" Grid.Row="4" AxisTitle="Ch2" Id="Ch2" Style="{StaticResource YAxisStyle}" /> <!-- 第 3 個 channel 數值綁定 -->
<s:NumericAxis x:Name="Ch3" Grid.Row="6" AxisTitle="Ch3" Id="Ch3" Style="{StaticResource YAxisStyle}" /> <!-- 第 4 個 channel 數值綁定 -->
<s:NumericAxis x:Name="Ch4" Grid.Row="8" AxisTitle="Ch4" Id="Ch4" Style="{StaticResource YAxisStyle}" /> <!-- 第 5 個 channel 數值綁定 -->
<s:NumericAxis x:Name="Ch5" Grid.Row="10" AxisTitle="Ch5" Id="Ch5" Style="{StaticResource YAxisStyle}" /> <!-- 第 6 個 channel 數值綁定 -->
</s:SciChartSurface.YAxes>
然後,在 C# 端,把 channel 數量做調整,就可以顯示 6 個頻道
//先定義好有幾個 channel public int channel_length = 6;
沒有留言:
張貼留言