2

Being new to F#, I'm trying to understand how to make graphic updates in a Form triggered by timer events. My expectation was that the below simple routine should continue drawing new "random" lines every second. Calling line() outside the timer event works seemingly without any problems, but I cannot get my head around why nothing gets displayed on the screen when the very same function is invoked via the timer event.

open System
open System.Drawing
open System.Windows.Forms

let form = new Form(Text="Simple Animation", Size=Size(400,500))
let pen = new Pen(Color.Red, 4.0f)
let random = new Random()

let line x = 
    let flexRight = random.Next(29,300)
    form.Paint.Add (fun e -> e.Graphics.DrawLine(pen, 30, 30, 350, flexRight))

let timer=new Timer(Interval=1000, Enabled=true)
timer.Tick.Add(fun time -> line())

form.Show()
Application.Run(form)

Any help very much appreciated, Thanks.

4

1 回答 1

3

您的代码的主要问题是,在每个计时器滴答声中,只会将另一个全新的 事件处理程序添加到您的表单中,而不是调用将执行绘图Paint的单个注册回调。OnPaint

您可以摆脱您的line函数定义并注册一个Paint回调作为

form.Paint.Add(fun e -> e.Graphics.DrawLine(pen, 30, 30, 350, random.Next(29,300)))

然后可以在每个计时器Paint上触发滴答事件,例如,通过使表单无效。这可以通过将计时器的回调代码更改为

timer.Tick.Add(fun _ -> form.Invalidate())

整个行为符合预期的片段如下所示:

#r "System.Windows.Forms"

open System
open System.Drawing
open System.Windows.Forms

let form = new Form(Text="Simple Animation", Size=Size(400,500))
let pen = new Pen(Color.Red, 4.0f)
let random = new Random()

form.Paint.Add(fun e -> e.Graphics.DrawLine(pen, 30, 30, 350, random.Next(29,300)))

let timer=new System.Windows.Forms.Timer(Interval=1000, Enabled=true)
timer.Tick.Add(fun _ -> form.Invalidate())

form.Show()

更新:由于最初的意图是在表单上显示所有后续绘制的线的叠加,我提供了一种可能的方法来在GraphicsPath的帮助下适应这种行为。使用它需要对上面的代码片段进行以下更改:

  • 在添加表单Paint事件处理程序的行之前添加创建实例的行GraphicsPath

    let gp = new System.Drawing.Drawing2D.GraphicsPath()

  • Paint事件处理程序更改为

    form.Paint.Add(fun e -> gp.AddLine(30,30,350,random.Next(29,300)) e.Graphics.DrawPath(pen, gp))

于 2018-01-15T08:46:24.340 回答