2017-05-01 12 views
0

좋아, 기본적으로 DateTime을 대체하고 스톱워치를 기반으로 X 축을 플롯하기 위해이 그래프를 만들고 싶습니다. 그런 다음 데이터를 직렬 포트에서 가져 와서 Y 축에 데이터를 그려야합니다. 이것은 버튼을 눌러서 생생하게 살아야합니다.시간과 시리얼 포트에서 읽은 값을 기반으로 점을 그리는 라이브 차트 상수 변경의 예는 무엇입니까?

https://lvcharts.net/App/examples/v1/wpf/Constant%20Changes

그것의 문제, 그것은 일종의 스톱워치보다는 시스템 시간을 사용한다는 것입니다 : 여기

내가 다음에 예입니다. WPF를 사용하고 있으며이 그래프의 기능을 확장하고 싶습니다.

누군가가 스카 이프 등을 통해 나를 도울 수 있다면. 저에게 알려주세요!

결국 그래프에서 모든 데이터를 가져 와서 어딘가에 저장할 수 있기를 원합니다. 그래서 이전에 비교할 수 있습니다.

감사합니다!

Mainwindow.cs.xaml

<Window x:Class="TestChartProject.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:TestChartProject" 
    xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"></RowDefinition> 
     <RowDefinition Height="*"></RowDefinition> 
    </Grid.RowDefinitions> 
    <Button Grid.Row="0" Click="InjectStopOnClick"> 
     Inject/Stop Data 
    </Button> 
    <!--Here we disable tooltips and hovering to get a better performance--> 
    <lvc:CartesianChart Grid.Row="1" AnimationsSpeed="0:0:1" Hoverable="True" DataTooltip="{x:Null}"> 
     <lvc:CartesianChart.Series> 
      <lvc:LineSeries Values="{Binding ChartValues}" 
          PointGeometry="{x:Null}" 
          LineSmoothness="1" 
          StrokeThickness="6" 
          Stroke="#F34336" 
          Fill="Transparent"/> 
     </lvc:CartesianChart.Series> 



     <lvc:CartesianChart.AxisX> 


      <lvc:Axis LabelFormatter="{Binding DateTimeFormatter}" 
         MaxValue="{Binding AxisMax}" 
         MinValue="{Binding AxisMin}" 
         Unit="{Binding AxisUnit}"> 
       <lvc:Axis.Separator> 
        <lvc:Separator Step="{Binding AxisStep}" /> 
       </lvc:Axis.Separator> 
      </lvc:Axis> 




     </lvc:CartesianChart.AxisX> 



    </lvc:CartesianChart> 
</Grid> 

MainWindow.cs

private double _axisMax; 
    private double _axisMin; 
    private double _trend; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     //To handle live data easily, in this case we built a specialized type 
     //the MeasureModel class, it only contains 2 properties 
     //DateTime and Value 
     //We need to configure LiveCharts to handle MeasureModel class 
     //The next code configures MeasureModel globally, this means 
     //that LiveCharts learns to plot MeasureModel and will use this config every time 
     //a IChartValues instance uses this type. 
     //this code ideally should only run once 
     //you can configure series in many ways, learn more at 
     //http://lvcharts.net/App/examples/v1/wpf/Types%20and%20Configuration 

     var mapper = Mappers.Xy<MeasureModel>() 
      .X(model => model.Session.Ticks) //use DateTime.Ticks as X 
      .Y(model => model.Value);   //use the value property as Y 

     //lets save the mapper globally. 
     Charting.For<MeasureModel>(mapper); 

     //the values property will store our values array 
     ChartValues = new ChartValues<MeasureModel>(); 

     //lets set how to display the X Labels 
     DateTimeFormatter = value => new DateTime((long)value).ToString("mm:ss"); 

     //AxisStep forces the distance between each separator in the X axis 
     AxisStep = TimeSpan.FromSeconds(1).Ticks; 
     //AxisUnit forces lets the axis know that we are plotting seconds 
     //this is not always necessary, but it can prevent wrong labeling 
     AxisUnit = TimeSpan.TicksPerSecond; 

     SetAxisLimits(DateTime.Now); 

     //The next code simulates data changes every 300 ms 

     IsReading = false; 

     DataContext = this; 
    } 

    public ChartValues<MeasureModel> ChartValues { get; set; } 
    public Func<double, string> DateTimeFormatter { get; set; } 
    public double AxisStep { get; set; } 
    public double AxisUnit { get; set; } 

    public double AxisMax 
    { 
     get { return _axisMax; } 
     set 
     { 
      _axisMax = value; 
      OnPropertyChanged("AxisMax"); 
     } 
    } 
    public double AxisMin 
    { 
     get { return _axisMin; } 
     set 
     { 
      _axisMin = value; 
      OnPropertyChanged("AxisMin"); 
     } 
    } 

    public bool IsReading { get; set; } 

    private void Read() 
    { 
     var r = new Random(); 

     while (IsReading) 
     { 
      Thread.Sleep(1); 
      var now = DateTime.Now; 


      _trend = r.Next(100); 

      ChartValues.Add(new MeasureModel 
      { 
       Session = now, 
       Value = _trend 
      }); 

      SetAxisLimits(now); 

      //lets only use the last 150 values 
      if (ChartValues.Count > 10) ChartValues.RemoveAt(0); 
     } 
    } 

    private void SetAxisLimits(DateTime now) 
    { 
     AxisMax = now.Ticks + TimeSpan.FromSeconds(1).Ticks; // lets force the axis to be 1 second ahead 
     AxisMin = now.Ticks - TimeSpan.FromSeconds(8).Ticks; // and 8 seconds behind 
    } 

    private void InjectStopOnClick(object sender, RoutedEventArgs e) 
    { 
     IsReading = !IsReading; 
     if (IsReading) Task.Factory.StartNew(Read); 
    } 

    #region INotifyPropertyChanged implementation 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName = null) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion 
} 

MeasureModel 나는 당신이 필요로하는 무슨 생각을 바탕으로

public class MeasureModel 
{ 
    public DateTime Session { get; set; } 
    public double Value { get; set; } 
} 

답변

0

은, 어쩌면이 당신을 도와줍니다 :

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     //used to generate random values 
     var r = new Random(); 
     var t = 0d; 

     //lets instead plot elapsed milliseconds and value 
     var mapper = Mappers.Xy<MeasureModel>() 
      .X(x => x.ElapsedMilliseconds) 
      .Y(x => x.Value); 

     //save the mapper globally   
     Charting.For<MeasureModel>(mapper); 

     Values = new ChartValues<MeasureModel>(); 
     var sw = new Stopwatch(); 
     sw.Start(); 

     Task.Run(() => 
     { 
      while (true) 
      { 
       Thread.Sleep(500); 

       //we add the lecture based on our StopWatch instance 
       Values.Add(new MeasureModel 
       { 
        ElapsedMilliseconds = sw.ElapsedMilliseconds, 
        Value = t += r.Next(0,10) 
       }); 
      } 
     }); 

     DataContext = this; 
    } 

    public ChartValues<MeasureModel> Values { get; set; } 
} 

public class MeasureModel 
{ 
    public double ElapsedMilliseconds { get; set; } 
    public double Value { get; set; } 
} 

XAML :

<lvc:CartesianChart> 
     <lvc:CartesianChart.Series> 
      <lvc:LineSeries Values="{Binding Values}" /> 
     </lvc:CartesianChart.Series> 
    </lvc:CartesianChart> 
+0

신난다! 제가 가진 유일한 질문은 X 축에 있습니다. 이것은 형식이 아닌 임의의 숫자를 내게 제공합니다. 나는 이렇게 생각한다 : "Minutes : Seconds". 감사! – Hypergyzed