[英]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. 将其声明移动到定义
position
和g
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.