f# 定时器事件 graphics.LineDraw 不更新表单

f# timer event graphics.LineDraw not updating form

作为 F# 的新手,我想了解如何在由计时器事件触发的窗体中进行图形更新。 我的期望是下面的简单例程应该每秒继续绘制新的 "random" 行。 在定时器事件之外调用 line() 似乎没有任何问题,但我不明白为什么当通过定时器事件调用相同的函数时屏幕上什么也没有显示。

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)

非常感谢任何帮助,谢谢。

你的代码的主要问题是,在每个计时器滴答声中,只有另一个 全新的 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))