610 likes | 718 Views
three. objects, classes, and hierarchies. This lecture will be long…. Sorry This is going to be the big programming lecture of the quarter It’s really about teaching you object-oriented programming But we need a source of examples, so we’ll also teach you about
E N D
three objects, classes, and hierarchies
This lecture will be long… • Sorry • This is going to be the big programming lecture of the quarter • It’s really about teaching you object-oriented programming • But we need a source of examples, so we’ll also teach you about • GUI programming (windows, buttons, sliders, etc.) • “Collection classes” • Low-level windows graphics calls • Don’t get too hung up on the examples • What we really want you to understand is • What classes and subclasses • What fields and methods are • How to make new classes • How to make new methods
The story up until now • Everything in your computer is data • Including programs • Data is divided into objects • Objects can be “inside” of other objects • Boxes inside groups • Colors inside bitmaps • Objects have types (or: “classes”) • Procedures • Numbers (1, -3.5) • Strings (“this is a string”, “blue”) • Bitmaps • Picture objects (lines, groups, boxes, etc.)
Looking inside data objects Ellipse Width: 15 Height: 10 • Data objects are like forms • They have fields (aka members) • Filled in by values • The fields • Have names (Width, Height) • The fields are filled in by other data objects • The object’s type (Box, Color) determines what fields it has Box Width: 10 Height: 10 Number Value: 10 Procedure Name: iterated-group Arguments: proc count Body: [apply group [up-to count proc]] Color R: 240 G: 220 B: 0
Types and subtypes Object • Types often have subtypes • Integers are a subtype of numbers • Boxes are a subtype of Pictures • All types are subtypes of the magic type Object • Subtyping means objects can have many types • All Integers are also Numbers • All Boxes are also Pictures • And all objects are Objects List Number Array Integer Float Picture Box Line Group
Example 1:The Windows Forms class hierarchy Control • User-interface components (windows, buttons, etc.) are all objects • Individual windows are Form objects • Individual elements of windows are objects of type Button, TextBox, Label, etc. • Form, Button, etc. are all subtypes of the type Control • Controls can have other Controls inside of them • Which is how buttons can be inside forms • All these classes are in the System.Windows.Forms namespace Form Button TextBox TrackBar PictureBox Label Greatly simplified version of the winforms class hierarchy
[new type arguments …] Creates a new object of the specified type The arguments depend on the type For windows forms classes, they generally don’t take any arguments Great, but how do we get at the data in the object? ► [define my-form [new Form]] Creating new data objects
Member notation Ellipse Width: 15 Height: 10 • You can ask for a field of a data object using the “.” notation: object.memberName • myColor.R • [pixel myBitmap 0 0].R • iterated-group.Name • iterated-group.Arguments • mybox.Width • Note: to simplify the presentation, I’ve lied here about what the actual fields of boxes, procedures, etc. are. • You can find out what fields are really in an object using the inspector. Box Width: 10 Height: 10 Number Value: 10 Procedure Name: iterated-group Arguments: proc count Body: [apply group [up-to count proc]] Color R: 240 G: 220 B: 0
These can be used to change the appearance of any control There are many more, but these should be enough for you for now. BackColor, ForeColor Background/foreground color for the control Font Font that text appears in (see the slide at the end for how to specify a font) Text Text that appears in the control (if any) Height, Width The size of the control Location The X,Y coordinate of the top-left corner (as a point) Left, Top The individual X- and Y- coordinates of the control within its window Fields of the Control class
Member procedures (aka “methods”) • Some of an object’s members are procedures • They act like they’re stored inside the object • You call them by saying: [object.nameargs …] • They are usually called methods • N.B.: “method” is also used to refer to a slightly different kind of procedure we’ll talk about in the next unit • Examples • [x.ToString]Returns a string that represents x • [g.DrawLine startx starty endx endy]Draws a line in a window given its
A form is a window that can hold controls It’s also a special kind of control, so you can set things like its Width, Height, BackColor, etc. [using System.Windows.Forms] Tells system to use classes in the Windows Forms namespace [new Form] Makes a form [form.Controls.Add control] Adds a control to a form [Application.Run form] Displays form and lets the user work with it until they close it. [form.Show] Used to show a new form after Application.Run has already been invoked The Form class
The TextBox control • [new TextBox] • Makes a space where the user can type • Whatever they type appears in the Text field of the object (remember the Text field?)
Example: entering text [define get-text[starting-text → [with* f = [new Form] make the Form tbox = [new TextBox] [f.Controls.Add tbox] [tbox.Text ← starting-text] [tbox.Width ← 150] [tbox.Location ← [point 10 10]] [Application.Run f] tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] make the TextBox [f.Controls.Add tbox] [tbox.Text ← starting-text] [tbox.Width ← 150] [tbox.Location ← [point 10 10]] [Application.Run f] tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] [f.Controls.Add tbox] add the TextBox to the Form [tbox.Text ← starting-text] [tbox.Width ← 150] [tbox.Location ← [point 10 10]] [Application.Run f] tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] [f.Controls.Add tbox] [tbox.Text ← starting-text] set Text to the default [tbox.Width ← 150] [tbox.Location ← [point 10 10]] [Application.Run f] tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] [f.Controls.Add tbox] [tbox.Text ← starting-text] [tbox.Width ← 150] make it 150 pixels wide [tbox.Location ← [point 10 10]] [Application.Run f] tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] [f.Controls.Add tbox] [tbox.Text ← starting-text] [tbox.Width ← 150] [tbox.Location ← [point 10 10]] put tbox at (10, 10) [Application.Run f] tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] [f.Controls.Add tbox] [tbox.Text ← starting-text] [tbox.Width ← 150] [tbox.Location ← [point 10 10]] [Application.Run f] let the user play with it tbox.Text]]]
Example: entering text [define get-text[starting-text → [with* f = [new Form] tbox = [new TextBox] [f.Controls.Add tbox] [tbox.Text ← starting-text] [tbox.Width ← 150] [tbox.Location ← [point 10 10]] [Application.Run f] tbox.Text]]] return the text they typed
You will find that you spend a lot of time calling new and then setting fields of the resulting object This can be tedious And hard to read The make command simplifies this by letting you simultaneously Make the object, and Set its fields [make [Type args …]field:value …] Runs [new Type args …] Then sets each field of the new object to its corresponding value N.B.: the colons are mandatory The make command
Rewriting using make [define get-text[starting-text → [with* f = [new Form] tbox = [make [TextBox] Text: starting-text Width: 150 Location: [point 10 10]] [f.Controls.Add tbox] [Application.Run f] tbox.Text]]]
Make is an example of a macro Macros are convenient shorthands for more complicated expressions Meta translates make into a call to new and a bunch of assignment statements (well, almost) Why are we telling you this? Because it means that if you use make incorrectly You probably won’t see make anywhere in the debugger You’ll see a call to new instead So we just don’t want you to be confused If you want to learn to write your own macros, talk to Ian Some macros you may have been using [when test expressions …][unless test expressions …] Gets translated to:[if test [begin expressions …]], or [if [not test] [begin expressions …]], respctvly [cond [test1 expressions …] [test2 expressions …]…etc…] Gets translated to:[if test1 [begin expressions …] [if test2 [begin expressions …]…etc…]] [define [name args …]expressions …] Gets translated to:[define name [args … → expressions …]] Aside: macros and syntactic sugar
This is okay, but it has some definite problems: You click the close box to finish (rather than an OK box) It doesn’t actually work because Application.Run turns out to clear the Text of tbox We’ll ignore this for the moment and pretend it works The window is outrageously tall We’ll leave fixing this as an exercise for the reader The window has no name You can fix this by setting its Text or Name field Three problems
Adding a button [define get-text[starting-text → [with* f = [new Form] b = [make [Button] Text: “OK” Location: [point 170 10]] tbox = [make [TextBox] Text: starting-text Width: 150 Location: [point 10 10]] [f.Controls.Add tbox] [f.Controls.Add b] [Application.Run f] tbox.Text]]]
Trying it out • Hey! We have a button! • Hey! It doesn’t do anything! • Hey! The window is still too tall and has no name! • Oh, shut up…
Event handling • You need some way of specifying what to do when the button is pressed • This is done by specifying a procedure called an “event handler” or a “callback” • When the even happens, the system calls the procedure
Event handling in Meta • Events look like lists of procedures to call when the event happens • To add a handler for an event, add it to the list: [object.event.Add handler-procedure] • Or specify it as part of the make arguments • Windows Forms always passes two parameters to the handler procedure • The control that generated the event • An extra data object that we’ll ignore for the moment
Adding a Click handler [define get-text[starting-text → [with* f = [new Form] b = [make [Button] Text: “OK” Location: [point 170 10] Click: [ignore ignore → [f.Close]]] tbox = [make [TextBox] Text: starting-text Width: 150 Location: [point 10 10]] [f.Controls.Add tbox] [f.Controls.Add b] [Application.Run f] tbox.Text]]]
Shortening the form [define get-text[starting-text → [with* f = [make [Form] Height: 75] b = [make [Button] Text: “OK” Location: [point 170 10] Click: [ignore ignore → [f.Close]]] tbox = [make [TextBox] Text: starting-text Width: 150 Location: [point 10 10]] [f.Controls.Add tbox] [f.Controls.Add b] [Application.Run f] tbox.Text]]]
Naming the form [define get-text[starting-text → [with* f = [make [Form] Height: 75Text: “Please enter some text”] b = [make [Button] Text: “OK” Location: [point 170 10] Click: [ignore ignore → [f.Close]]] tbox = [make [TextBox] Text: starting-text Width: 150 Location: [point 10 10]] [f.Controls.Add tbox] [f.Controls.Add b] [Application.Run f] tbox.Text]]]
It works! • In particular, clicking the OK box • Closes the form as if the user had click the close box • Which causes Application.Run to finish • Which causes get-text to finish and return the text
The TrackBar control • [new TrackBar] • Makes a slider control • Useful fields (plus Control’s fields) • Value • The current numeric value the user has chosen • Minimum, Maximum • The numeric values for the ends of the range of the slider • TickFrequency • How often to draw tick marks • Orientation • Whether it should be a horizontal or vertical control.Set it to either Orientation.Horizontal or Orientation.Vertical. • Useful events • ValueChanged (called when the user moves the slider)
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] make a form r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top:10] make three sliders to go with it g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → run this procedure on r, g, and b [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] add it to the form [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] make it 255 pixels wide [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] set its limits to 0 and 255 [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add add the following handler for when the slider changes [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add ignore arguments … and change the background color of the form[ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]] start the form up
Fixing a bug [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]] This what it looks like when you start it up. What’s wrong with this?
Fixing a bug [with f = [new Form] r = [make [TrackBar] Top: 10] g = [make [TrackBar] Top: 60] b = [make [TrackBar] Top: 110] [f.BackColor ← [color 0 0 0]] [for-each [slider → [f.Controls.Add slider] [slider.Width ← 255] [slider.Minimum ← 0] [slider.Maximum ← 255] [slider.ValueChanged.Add [ignore ignore → [f.BackColor ← [color r.Value g.Value b.Value]]]]] [list r g b]] [Application.Run f]]]
What does this do? [define slider-text [→ [with* f = [new Form] s = [make [TrackBar] Top: 10 ValueChanged: [i i → [t.Text ← [s.Value.ToString]]]] t = [make [TextBox] Top:60 TextChanged: [i i → [s.Value ← [System.Int32.Parse t.Text]]]] [f.Controls.Add s] [f.Controls.Add t] [Application.Run f]]]] • Hints: • [System.Int32.Parse string] returns the number represented by string.Example: [System.Int32.Parse “10”] returns 10 (the integer, not a string)
Fixing a bug [define slider-text [→ [with* f = [new Form] s = [make [TrackBar] Top: 10 ValueChanged: [i i → [t.Text ← [s.Value.ToString]]]] t = [make [TextBox] Top:60 TextChanged: [i i → [ignore-errors [→[s.Value ← [System.Int32.Parse t.Text]]]]] [f.Controls.Add s] [f.Controls.Add t] [Application.Run f]]]] • Ignore-errors runs its argument procedure and ignores any errors that occur
Some other useful Controls • [new Label] • Like a textbox but the user can’t change it • [new CheckBox] • Makes a box • Useful fields • Checked (whether the box has been checked (true or false))