2014-10-20 39 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 
相關問題