F# WPF脚本,点击按钮绘制图形

F# WPF script, draw graphics on button click

我正在尝试使用 F# 脚本,我只想通过单击按钮在空白 Windows 表单上画线。希望你能看到我在这里尝试做的事情:

open System.Drawing
open System.Windows.Forms

let form = new Form(Width = 400, Height = 400, Text = "draw test")
let panel = new FlowLayoutPanel()
form.Controls.Add(panel)

let paint(e : PaintEventArgs) =
    let pen = new Pen(Color.Black);  
    e.Graphics.DrawLine(pen, new PointF(100.0f, 100.0f), new PointF(200.0f, 200.0f))

let button = new Button()
button.Text <- "Click to draw"
button.AutoSize <- true

button.Click.Add(fun _ -> form.Paint.Add(paint)) // <- does not draw a line on click

panel.Controls.Add(button)

//form.Paint.Add(paint) <- here, if uncommented, it will draw a line when the script is run
form.Show()

如果我在 form.Show() 上面取消注释 form.Paint.Add(paint),那么它当然会在表单上绘制,但我正在尝试通过单击按钮来完成。我不太清楚如何在这样的脚本中实现这一点,我一直在四处寻找 F# 中的类似示例。任何帮助将不胜感激。

如果您在第一次绘制表单之前添加 Paint 事件处理程序,那么它将使用该处理程序进行绘制。

如果您在之后添加它,您需要确保表单随后会自行重绘。例如,您可以在其上调用 RefreshInvalidate。 例如:

button.Click.Add(fun _ -> form.Paint.Add(paint); form.Invalidate()) 

原来是编辑,我把它移到了答案部分:

好的,所以我对 WPF 和 Winforms 之间的区别感到困惑,因为我看到这些术语在不同的地方一起使用......@Asik 为 Winforms 添加了一个答案,但在这里我一起拍打基于几个 FSharp Snippets(以及几个 Google 搜索)的专门用于 WPF 的工作 .fsx 脚本,如果需要也可以编译。我会根据需要或请求更新此内容。另外,要指出的是,这背后的全部动机是能够通过 FSI 快速测试绘图图形。

#r @"PresentationCore"
#r @"PresentationFramework"
#r @"WindowsBase"
#r @"System.Xaml"
#r @"UIAutomationTypes"

open System
open System.Windows
open System.Windows.Media
open System.Windows.Shapes
open System.Windows.Controls

let window = Window(Height = 400.0, Width = 400.0)
window.Title <- "Draw test"
let stackPanel = StackPanel()
window.Content <- stackPanel
stackPanel.Orientation <- Orientation.Vertical

let button1 = Button()
button1.Content <- "Click me to draw a blue ellipse"
stackPanel.Children.Add button1

let button2 = Button()
button2.Content <- "Click me to draw a red ellipse"
stackPanel.Children.Add button2

let clearButton = Button()
clearButton.Content <- "Click me to clear the canvas"
stackPanel.Children.Add clearButton

let canvas = Canvas()
canvas.Width <- window.Width
canvas.Height <- window.Height
stackPanel.Children.Add canvas

let buildEllipse height width fill stroke =
    let ellipse = Ellipse()
    ellipse.Height  <- height
    ellipse.Width   <- width
    ellipse.Fill    <- fill
    ellipse.Stroke  <- stroke
    ellipse

let ellipse1 = buildEllipse 100.0 200.0 Brushes.Aqua Brushes.Black
Canvas.SetLeft(ellipse1, canvas.Width / 10.0) //messy, will fix at some point!
Canvas.SetTop(ellipse1, canvas.Height / 10.0)
let ellipse2 = buildEllipse 200.0 100.0 Brushes.Red Brushes.DarkViolet
Canvas.SetLeft(ellipse2, canvas.Width / 4.0)
Canvas.SetTop(ellipse2, canvas.Height / 5.0)

let addEllipseToCanvas (canvas:Canvas) (ellipse:Ellipse) =
    match canvas.Children with
    | c when c.Contains ellipse ->
        canvas.Children.Remove ellipse
        canvas.Children.Add(ellipse) |> ignore //needs to be removed and readded or the canvas complains
    | _ ->
        canvas.Children.Add(ellipse) |> ignore

button1.Click.Add(fun _ -> addEllipseToCanvas canvas ellipse1)
button2.Click.Add(fun _ -> addEllipseToCanvas canvas ellipse2)
clearButton.Click.Add(fun _ -> canvas.Children.Clear())

#if INTERACTIVE
window.Show()
#else
[<EntryPoint; STAThread>]
let main argv =
    let app = new Application()
    app.Run(window)
#endif