three objects, classes, and hierarchies. this lecture will be long… sorry this is going to be the...
TRANSCRIPT
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.)
NumberValue: 10
Looking inside data objects
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
BoxWidth: 10Height: 10
EllipseWidth: 15Height: 10
ProcedureName: iterated-groupArguments: proc countBody: [apply group [up-to count proc]]
ColorR: 240G: 220B: 0
Types and subtypes
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
ObjectList
Picture
Number
Integer Float Array
Box Line Group
Example 1:The Windows Forms class hierarchy
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
Control
Form TextBox
Label
Button TrackBar
PictureBox
Greatly simplified version of the winforms class hierarchy
Creating new data objects
[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]]
NumberValue: 10
Member notation
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.
BoxWidth: 10Height: 10
EllipseWidth: 15Height: 10
ProcedureName: iterated-groupArguments: proc countBody: [apply group [up-to count proc]]
ColorR: 240G: 220B: 0
Fields of the Control class 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
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.name args …] 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
The Form class
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 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
The make command
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
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]]]
Aside: macros and syntactic sugar
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 …]]
Three problems
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
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: 75 Text: “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))
Example 2:The container class hierarchy
An important area of computer science is the study of data structures
Roughly: how we put data objects together to make them useful
A very important kind of data structure is the container
A kind of object that “holds” a collection of other objects
There are many kinds of containers
Most of the container classes we’ll be using are subtypes of List
All the collection classes in .NET (and so in Meta) are in the namespace System.Collections
Collection
List Dictionary
Array ArrayList Stack Hashtable
Object[] String[] …
Lists
Have a bunch of elements Have them in a definite order
You can ask them how many elements they have
You can ask for an element at a specific position You can change the element at a specific
position
Basic list operations
[length list] or: list.CountTells you how many items are in the list
[get list position]Returns the element of list at position
[[get list position] ← new-value]Changes the element of list at position
The simplest list type: the array
An array is a fixed-length list Very fast and efficient Can’t add/remove element after creation Although you can change elements
The [list args …] procedure returns an array Technically, the type Object[] Which means an array of arbitrary objects There are other kinds of specialized arrays too
The ArrayList: a more powerful list type
ArrayLists can change size, but are less efficient
[using System.Collections]Access collection classes
[new ArrayList]Makes an ArrayList
[x.Add object] Add object to end of ArrayList x
[x.Insert position object] Adds element at the specified position
[x.Remove object] Removes all occurrences of object
[x.RemoveAt position] Remove element at position
[x.Clear]Removes all elements from x
«Some results omitted to save space»
►[using System.Collections] ►[define mylist
[new ArrayList]][ ]► [mylist.Add 98]► [mylist.Add 38]► [mylist.Add 4]► mylist[98 38 4]► [mylist.Remove 38]► mylist[98 4]► [mylist.Insert 1 “test”]► mylist[98 “test” 4]►
The stack: a simpler collection class
Stacks can only be changes at their “top” or beginning
[new Stack]Makes a new stack
[s.Push object]Adds a new object to the “top” of the stack s
[s.Pop]Removes the item at the top of s and returns it
[s.Peek]Returns the item at the top of s without removing it
[s.Clear]Removes all data from s
► [define s [new Stack]]‹System.Collections.Stack›► [s.Push 1]► [s.Push 2]► [s.Push 3]► [s.Peek]3► [s.Peek]3► [s.Pop]3► [s.Pop]2► [s.Pop]1► [s.Pop]Error: Stack empty.
Dictionary classes
Dictionaries are objects that store associations between pairs of objects One object is called the key The other the value
The most common dictionary class is the Hashtable
The Hashtable class
[new Hashtable]Makes a new hashtable
[lookup dict key] Returns the object listed in dict under key Or null if key doesn’t appear in dict
[store-dictionary dict key value]or: [[lookup dict key] ← value]
Adds or changes the entry for key in dict to value
[dict.Clear]Removes all entries from dict
[dict.Contains key]Checks whether dict contains an entry for key
► [define h [new Hashtable]]► [lookup h “test”]null► [[lookup h “test”] ← “got it”]"got it"► [[lookup h “test2”] ←
“something different”]"something different" ► [lookup h “test”]"got it"► [[lookup h “test”] ←
“changed it”]"changed it"► [lookup h “test”]"changed it"
How do I specify a font?
Just type:
[new Font fontfamily [System.Convert.ToSingle size] style]
where:
Fontfamily is a string, like “Times New Roman” Size is a number (the size of the font in points), e.g. 10 or 12 Style is one of:
FontStyle.Regular, FontStyle.Bold, FontStyle.Italic, FontStyle.Strikeout, FontStyle.Underline
How do we fix get-text to return the stupid text?
Change:[with* f = [new Form] b = [new Button] tbox = [new TextBox]
… bla bla bla …
[Application.Run f] tbox.Text]
To:[with* f = [new Form] b = [new Button] tbox = [new TextBox] remember = starting-text
… bla bla bla …
[tbox.TextChanged.Add [ignore ignore → [remember ← tbox.Text]]]
[Application.Run f] remember]
We add a new event handler that runswhenever the user changes the text