Drawing in a Windows Form in F#
drawing, f#, winforms
Solution
You have one error in conectar.
fUtil gr caneta resto.Tail resto.Head
Should be
fUtil gr caneta resto ponto
You're already matching the head and tail inside of the match statement.
The following code draws a line for me. I didn't have to modify much.
open System.Drawing
open System.Windows.Forms
let caneta = new Pen(brush = Brushes.Black, width = 1.0f)
let original =
([|new PointF(50.0f, 50.0f); new PointF(100.0f, 50.0f)|])
let form1 = new Form(Width = 400, Height = 400, Text = "Fractais (Teste - Windows Forms)")
let conectar (gr:Graphics) (caneta:Pen) (pontos:PointF list) =
let rec fUtil (gr:Graphics) (caneta:Pen) (pontos:PointF list) pontoAnt =
match pontos with
| [] -> ()
| ponto :: resto ->
gr.DrawLine (caneta, pontoAnt, ponto)
fUtil gr caneta resto ponto
fUtil gr caneta pontos.Tail pontos.Head
form1.Paint.Add(
fun e -> // (1)
original
|> List.ofArray
//|> aplicFractal 1uy Base.funcFractal1
|> conectar e.Graphics caneta)
form1.Show()
Application.Run(form1)
Problem
I'm attempting to draw in a non-customized (I mean, simply creating an instance of the default form class, not an instance of a deriving class I can create) `System.Windows.Forms.Form` in F#. I had created a custom form, but I didn't need nor want a new complex structure like that, so I removed it, and it simplified the code a lot; so much, that it stopped to show an image. The problem must be in the function I created to draw, that is in another F# project. I've created it (function `conect`) to connect points in the order they are provided, unlike `System.Drawing.Graphics.DrawLines`, that draws lines between the points in some other order why haven't noticed yet (maybe right to left, top to bottom, as the points are represented). Programa.fs relevant code snippet: ``` let pen = new Pen(brush = Brushes.Black, width = 1.0f) let original = ([|new PointF(50.0f, 50.0f); new PointF(100.0f, 50.0f)|]) use form1 = new Form(Width = 400, Height = 400, Text = "Fractais (Teste - Windows Forms)") form1.Paint.Add( fun e -> // (1) original |> List.ofArray |> Base.applyFractal 1uy Base.fractalFunc1 |> Base.conect e.Graphics pen) ``` If in the lambda expression instead of what's written there was `e.Graphics.DrawLines(pen, original)`, it would draw a simple line between the points in the list. Here's the troublemaker method, in Base.fs, across the solution: ``` let conect (gr:Graphics) (pen:Pen) (points:PointF list) = let rec usefulFunc (gr:Graphics) (pen:Pen) (points:PointF list) prevPoint = match points with | [] -> () | point :: remainings -> gr.DrawLine (pen, prevPoint, point) usefulFunc gr caneta remainings.Tail remainings.Head usefulFunc gr pen points.Tail points.Head ``` And the called (from the form initialization snippet) and relevant methods' signatures, in Base.fsi (I could give you all of the full methods' implementation, but it would take a lot of space, and this is probably for you already becoming a long question to read): ``` val fractalFunc1 : points:PointF list -> PointF list val applyFractal : stepNumber:byte -> fractalFunc:(PointF list -> PointF list) -> points:PointF list -> PointF list val conect : gr:Graphics -> pen:Pen -> points:PointF list -> unit ``` For this specific problem, my search results were none. I'd like to know how can I make the function `conect` work. Thanks in advance.