2014-10-20 38 views
1

我一直想弄清楚如何用F#创建一个图表,使用FSharpCharting库,它显示了一个滑动的数据窗口。例如,我希望能够显示过去3分钟的所有值。比这更早的值会从图表中消失,并在观察到新值时被替换。是否可以使用或扩展FSharpChart库来创建滑动窗口的折线图?

基于我的实验,我不认为底层的Microsoft图表控件支持这种情况。有谁知道是否可以创建这种类型的图表?是否有其他替代方案具备此功能?

这是我试过的'实验'。更新系列值的任务产生例外

System.InvalidOperationException:集合已被修改;枚举操作可能不会执行。

#r "System.Windows.Forms.DataVisualization.dll" 

open System.Drawing 
open System.Collections.ObjectModel 
open System.Windows.Forms 
open System.Windows.Forms.DataVisualization.Charting 

/// Add data series of the specified chart type to a chart 
let addSeries typ (chart:Chart) = 
    let series = new Series(ChartType = typ) 
    chart.Series.Add(series) 
    series 

/// Create form with chart and add the first chart series 
let createChart typ = 
    let chart = new Chart(Dock = DockStyle.Fill, 
          Palette = ChartColorPalette.Pastel) 
    let mainForm = new Form(Visible = true, Width = 700, Height = 500) 
    let area = new ChartArea() 
    area.AxisX.MajorGrid.LineColor <- Color.LightGray 
    area.AxisY.MajorGrid.LineColor <- Color.LightGray 
    mainForm.Controls.Add(chart) 
    chart.ChartAreas.Add(area) 
    chart, addSeries typ chart 

let numbers = 
    seq { while true do for i in 0.0 .. 0.1 .. 45.0 do yield i } 
    |> Seq.map sin 

let dataWindow = new ObservableCollection<double>() 

numbers 
|> Seq.take 100 
|> Seq.iter dataWindow.Add 

let chart, series = createChart SeriesChartType.Line 
series.BorderWidth <- 3 
series.Points.DataBindY(dataWindow) 

async{ 
    for number in numbers do 
     series.Points.RemoveAt(0) 
     series.Points.Add(number) |> ignore 
} 
|> Async.Start 
+0

你见过FSharp.Charting网站上的活动图表示例吗?他们可能会帮助。 http://fsharp.github.io/FSharp.Charting/LiveChartSamples.html – 2014-10-22 22:40:07

+0

谢谢。我可能可以调整第一个图表,以便在我想要的序列上使用某种窗口。 – 2014-10-23 14:14:24

回答

2

我能够通过避免DataBindY通话,并且明确地添加和删除点使这样的工作。

#r "System.Windows.Forms.DataVisualization.dll" 

open System 
open System.Drawing 
open System.Threading 
open System.Windows.Forms 
open System.Windows.Forms.DataVisualization.Charting 

/// Add data series of the specified chart type to a chart 
let createSeries typ (chart:Chart) = 
    let series = new Series(ChartType = typ) 
    chart.Series.Add(series)  
    series 

/// Create form with chart and add the first chart series 
let createChart() = 
    let chart = new Chart(Dock = DockStyle.Fill, 
          Palette = ChartColorPalette.Pastel) 
    let mainForm = new Form(Visible = true, Width = 700, Height = 500) 
    let area = new ChartArea() 
    area.AxisX.MajorGrid.LineColor <- Color.LightGray 
    area.AxisY.MajorGrid.LineColor <- Color.LightGray 
    mainForm.Controls.Add(chart) 
    chart.ChartAreas.Add(area) 
    chart 

let numbers = 
    seq { while true do for i in 0.0 .. 0.1 .. Double.MaxValue do yield i } 
    |> Seq.map sin 

let chart = createChart() 
let series = createSeries SeriesChartType.FastLine chart 

let firstWindow = numbers |> Seq.take 100 

for number in firstWindow do 
    series.Points.AddY(number) |> ignore 

let context = SynchronizationContext.Current 
let numbersEnumerator = numbers.GetEnumerator() 
async{ 
    do! Async.SwitchToContext context 
    while(numbersEnumerator.MoveNext() && not chart.IsDisposed) do   
     let number = numbersEnumerator.Current 
     series.Points.SuspendUpdates() 
     series.Points.RemoveAt(0) 
     series.Points.AddY(number) |> ignore 
     series.Points.ResumeUpdates() 
     do! Async.SwitchToThreadPool() 
     do! Async.Sleep(100) 
     do! Async.SwitchToContext context 
} 
|> Async.Start 
相关问题