简体   繁体   English

在覆盖onPaint方法F#的构造函数中定义的访问列表

[英]Access lists defined in constructor on override onPaint method F#

I want to override the onPaint method to make it draw the objects in two lists defined in the constructor, problem being I can't access the lists from the overrided onPaint method, I get the error saying the list or constructor is not defined when trying to use listOfSquares or listOfCircles. 我想覆盖onPaint方法,使其在构造函​​数中定义的两个列表中绘制对象,问题是我无法从覆盖的onPaint方法访问列表,我得到的错误是在尝试时没有定义列表或构造函数使用listOfSquares或listOfCircles。 So basically, how do I access these lists from that override? 所以基本上,如何从覆盖中访问这些列表?

type MainForm = class
  inherit Form

  val mutable g : Graphics // mutable means its not read-only
  val mutable position : Point // position of the rectangle

  new () as form = {g=null;position = new Point(0,0)} then
     // double buffering
     form.SetStyle (ControlStyles.UserPaint, true);
     form.SetStyle (ControlStyles.DoubleBuffer, true);
     form.SetStyle (ControlStyles.AllPaintingInWmPaint, true);
     form.Width <- 900
     form.Height <- 500
     form.BackColor <- Color.White
     form.Text <- "2D Graphics Editor";
     let listOfSquares = ResizeArray()
     let listOfCircles = ResizeArray()
     let menu = new MenuStrip()

     let file = new ToolStripDropDownButton("File") // Menu
     ignore(menu.Items.Add(file))


     let create = new ToolStripDropDownButton("Create")  // Menu
     ignore(menu.Items.Add(create))

     let square = create.DropDownItems.Add("Square")
     let circle = create.DropDownItems.Add("Circle")
     let newFile = file.DropDownItems.Add("New file")
     let saveFile = file.DropDownItems.Add("Save file")
     let openFile = file.DropDownItems.Add("Open file")
     square.Click.Add(fun _ -> listOfSquares.Add(new square(5.0, 5.0)) |> ignore)
     circle.Click.Add(fun _ -> listOfCircles.Add(new circle(10.0, 10.0)) |> ignore)
     newFile.Click.Add(fun _ -> MessageBox.Show("newFile") |> ignore)
     saveFile.Click.Add(fun _ -> MessageBox.Show("saveFile") |> ignore)
     openFile.Click.Add(fun _ -> MessageBox.Show("openFile") |> ignore)
     let dc c = (c :> Control)
     form.Controls.AddRange([|dc menu|]);


     // show the form
     form.Show()

     // override of paint event handler
     override form.OnPaint e = 
        let g = e.Graphics in
        // draw objects in listOfSquares and listOfCircles

     end  

You defined their scope as being the constructor rather than the object. 您将其范围定义为构造函数而不是对象。 Move their declarations up to where position and g are defined. 将其声明移动到定义positiong position

I think this satisfies your requirements: 我认为这符合您的要求:

type test =
    val mutable private temp:int
    new() as this = {temp=5} then
        this.temp <- 6

The important bits are the private access modifier, the assignment of the private field in the secondary constructor using the {..} syntax and the use of this to access private members. 重要的位是private访问修饰符,使用{..}语法在辅助构造函数中分配私有字段,并使用this来访问私有成员。

Here is your code rewritten to properly initialize your lists: 以下是您重写的代码,以正确初始化您的列表:

type MainForm =
  inherit Form

  val mutable g : Graphics // mutable means its not read-only
  val mutable position : Point // position of the rectangle
  val listOfSquares : ResizeArray
  val listOfCircles : ResizeArray

  new () as form = {g=null;position = new Point(0,0)} then
     // double buffering
     form.SetStyle (ControlStyles.UserPaint, true);
     form.SetStyle (ControlStyles.DoubleBuffer, true);
     form.SetStyle (ControlStyles.AllPaintingInWmPaint, true);
     form.Width <- 900
     form.Height <- 500
     form.BackColor <- Color.White
     form.Text <- "2D Graphics Editor";
     listOfSquares <- ResizeArray()
     listOfCircles <- ResizeArray()
     let menu = new MenuStrip()

     let file = new ToolStripDropDownButton("File") // Menu
     ignore(menu.Items.Add(file))


     let create = new ToolStripDropDownButton("Create")  // Menu
     ignore(menu.Items.Add(create))

     let square = create.DropDownItems.Add("Square")
     let circle = create.DropDownItems.Add("Circle")
     let newFile = file.DropDownItems.Add("New file")
     let saveFile = file.DropDownItems.Add("Save file")
     let openFile = file.DropDownItems.Add("Open file")
     square.Click.Add(fun _ -> listOfSquares.Add(new square(5.0, 5.0)) |> ignore)
     circle.Click.Add(fun _ -> listOfCircles.Add(new circle(10.0, 10.0)) |> ignore)
     newFile.Click.Add(fun _ -> MessageBox.Show("newFile") |> ignore)
     saveFile.Click.Add(fun _ -> MessageBox.Show("saveFile") |> ignore)
     openFile.Click.Add(fun _ -> MessageBox.Show("openFile") |> ignore)
     let dc c = (c :> Control)
     form.Controls.AddRange([|dc menu|]);


     // show the form
     form.Show()

     // override of paint event handler
     override form.OnPaint e = 
        let g = e.Graphics in
        // draw objects in listOfSquares and listOfCircles

     end  

As @leafgarland demonstrated, if you don't need to use a secondary constructor, then use the primary constructor for much cleaner syntax. 正如@leafgarland演示的那样,如果您不需要使用辅助构造函数,那么使用主构造函数可以获得更清晰的语法。

type test() =
    let mutable temp = 6

    ...

    override form.OnPaint e = 
        let g = e.Graphics
        printfn "%i" temp

If you did want to use a primary constructor then you could do it like this, using let bindings for all your private fields and do bindings for the constructor's code. 如果你确实想要使用主构造函数,那么就可以这样做,使用let绑定所有私有字段并对构造函数的代码进行绑定。 The let bindings are accessible to all non-static members. 所有非静态成员都可以访问let绑定。

See the F# documentation on classes to read about this syntax. 请参阅有关类F#文档以阅读有关此语法的信息。

type MainForm() as form =
    inherit Form()

    let mutable g : Graphics = null
    let mutable position : Point = Point(0,0)

    let listOfSquares = ResizeArray()
    let listOfCircles = ResizeArray()

    do
        form.SetStyle (ControlStyles.UserPaint, true);

        // ... your other initialization code

        // show the form
        form.Show()

    override form.OnPaint e = 
        let g = e.Graphics
        // draw objects in listOfSquares and listOfCircles

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM