Livecharts Constant Changes 예제를 사용하여 시간을 기준으로 포인트를 플로팅하고 직렬 포트에서 판독합니까?

Hypergyzed

좋습니다. 기본적으로이 그래프를 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; }
}
bto.jdz

내가 필요하다고 생각하는 것을 기반으로 할 때 도움이 될 수 있습니다.

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>

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관