作为F#的新手,我正在尝试了解如何在由计时器事件触发的表单中进行图形更新。
我的期望是下面的简单程序应该每秒继续绘制新的“随机”线。
在计时器事件之外调用SELECT DISTINCT a.title_id, a.artist_id, fe_title.title, fe_artist.artist
FROM fe_title_artist AS a
INNER JOIN fe_title ON a.title_id = fe_title.id
INNER JOIN fe_artist ON a.artist_id = fe_artist.id
INNER JOIN fe_title_artist AS b
WHERE a.title_id=b.title_id
and b.artist_id=(SELECT id FROM fe_artist WHERE artist LIKE '%Patrick%')
似乎没有任何问题,但我无法理解为什么当通过计时器事件调用相同的函数时,屏幕上没有显示任何内容。
line()
非常感谢任何帮助,谢谢。
答案 0 :(得分:4)
代码的主要问题是,在每个计时器上,只有另一个全新的 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()
UPDATE:因为它出现了原始意图在表单上显示所有后续绘制线的叠加,我提供了一种在{{3}的帮助下适应此类行为的可能方法}。利用它需要对上面的代码段进行以下更改:
在添加表单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))