What you should already know…. (Appendices C, D, and E) Review of OOP in Java What you should already know…. (Appendices C, D, and E)
Outline Encapsulation Inheritance Polymorphism data and operations together in one place insignificant details hidden Inheritance one class a specialized version of another Polymorphism allowing arguments based on what they can do, not (necessarily) on what they are
Data Structures Course Learning about useful data structures Primitive data types int, double, boolean, char, … each has operators (+, –, *, /, &&, ||, !, …) Structured data types have parts that we can refer to in our programs Strings (have characters) Scanners (have sources, delimiters and locales)
Structured Data Types in OOP Structured data encapsulated in classes data held by an object of this class Insignificant parts are hidden don’t really care how the type is implemented implementation may change with next release Operations available as methods of class this is what the object does consistent from one release to another
Classes and Objects Class encapsulates data and operations keeps them together in one place String name = "Mark Young"; // data int len = name.length(); // 10 int space = name.indexOf(" "); // 4 (sic) String city = "Wolfville"; // more data String animal = city.substring(0,4); // “Wolf” Class: String objects: “Mark Young”, “Wolfville”, “Wolf” object variables: name, city, animal
Classes, Objects and Variables Class is a kind of thing; a data type the kind of data and the available operations Object is an instance of the class; something a variable can refer to variables refer to, or point to, objects String variables String objects String operations & name: “Mark Young” get length find index of get substring … & city: “Wolfville” & animal: “Wolf”
Reference and Co-Reference Two variables can refer to the same object Car myCar = new Car(blue); // data Car disCar = myCar; // same object Car steves = new Car(blue); // same data disCar.setColor(green); // myCar is now green Car variables Car objects Car operations & myCar: … get colour change colour & disCar: & stevesCar:
Data What we know about objects of this class class says what type it is object holds information Class Name: Car Data: make: (String) model: (String) year: (int) fuel (l): (double) mileage (km): (double) colour: (Color) Operations: … & myCar: make: Toyota model: Corolla year: 2009 fuel (l): 23.7 mileage (km): 164054.0 colour: RED
Operations What we can do with objects of this class class says what’s available object carries out actions Class Name: Car Data: … Operations: get mileage drive some distance add fuel get colour change colour make: Toyota model: Corolla year: 2009 fuel (l): 23.7 mileage (km): 164054.0 colour: RED myCar make: Toyota model: Corolla year: 2009 fuel (l): 17.4 mileage (km): 164150.3 colour: RED myCar myCar, drive 96.3 km.
Getters and Setters Methods to get some part of object’s data getter: getMileage, getFuel, getColor, … most (non-final) IVs will have getters Methods to change some part of data setter: setColor no setters for final instance variables no setters for fuel and mileage but addFuel and drive will change them (“mutaters”) “immutable” objects have no setters at all!
Constructors Put the initial information into the object use “new” command give required data assign to a variable (usu.) Car myCar = new Car( "Toyota", "Corolla", 2009, Color.RED); fuel and mileage start at 0.0 / myCar & make: / model: / year: 0 fuel (l): 0.0 mileage (km): 0.0 colour: / make: Toyota model: Corolla year: 2009 fuel (l): 0.0 mileage (km): 0.0 colour: RED
Constructor Purpose Make sure every instance variable gets a reasonable value what the client asks for it to be, if possible some reasonable default if client doesn’t say may depend on what else client asks for Constructor is only place where a final variable can be given a value
Inheritance Reuse existing code to create new types but not copy-and-paste! New class a specialized version of old class Car is a specialized Vehicle Student is a specialized Person GradStudent is a specialized Student In Java we say one class extends another Car extends Vehicle, Student extends Person
Composition vs. Inheritance Don’t confuse inheritance with composition Composition: “has a” Person has a Name Car has a Color Inheritance: “is a” Name is not a Person; Person is not a Name Student is a Person; doesn’t have a Person
Polymorphism Subclass is a superclass so when we need a superclass object… …a subclass object will do Need a Person? Use a Student! public static void greet(Person p) { … } Person guy = new Person(); Student stu = new Student(); greet(guy); // guy is a Person greet(stu); // stu is a Person (all Students are)
Interfaces Basically a list of method headers Represent a “skill set” operations something might be able to do Represent a “skill set” says “what” but not “how” Sample interfaces List<T>: can keep track of a list of T objects T is any reference type (class or interface) Comparable<T>: can be compared to T objects Comparator<T>: can compare T objects
Polymorphism Interfaces can be used as data types public static double roundness(Measurable m) { return 4 * Math.PI * m.getArea() / Math.pow(m.getPerimeter(), 2); } any class that implements the interface will do but it has to say that it implements the interface…. double rc = roundness(new Circle(10.0)); double rr1 = roundness(new Rectangle(10.0, 20.0)); double rr2 = roundness(new Rectangle(0.4, 1000.0)); 1.0 rc 0.698132 rr1 0.001256 rr2
GUI as an Example of OOP Encapsulation of a GUI application javafx.application: Application Inheritance relations and components javafx.scene.control Parent, Pane, StackPane, GridPane, … Control, Button, Label, TextField, … Polymorphism and responding to actions javafx.event: EventHandler<T>
Our Goal Program opens up a window like this: What can we do with it? can enter numbers into the first and second number boxes can click the “Add” button to put their sum into the result box can click the “Done” button to end the program
Relevant Data Types GUI is an Application In window are Controls Labels, TextFields and Buttons Items laid out in a GridPane rows and columns of controls Buttons generate Events when clicked Events handled by EventHandlers
Encapsulation: Application Encapsulates (most) of what a GUI is Has a Stage (javafx.stage) the window the GUI is in may create other stages as it goes along You set a Scene (javafx.scene) on the stage contains root object for window’s contents also contains general event handlers You subclass this class to create an app
Application Methods All operations called by Application.launch creates the application (calls constructor) initializes the application (calls init) starts the application (calls start) closes the application (calls stop) main method calls Application.launch public static void main(String[] args) { Application.launch(args); }
Sub-Typing Application Create a class that extends Application public class AdderApplication extends Application Specify at least the start method @Override public void start(Stage primaryStage) { … } start method can create all the contents or you can split that between the constructor, init and start
Creating an Application Generally take these steps create and lay out the controls create the scene (i.e. attach contents to screen) add event handlers for scene set the stage (title, special properties) show the stage
Our Application start Method @Override public void start(Stage stage) { GridPane root = createControls(); Scene scene = new Scene(root); addAccelerators(scene); stage.setTitle("Adder Window"); stage.setScene(scene); stage.setResizable(false); stage.sizeToScene(); stage.show(); }
Inheritance: JavaFX Nodes Nodes are the visible items in a window except for Menus and MenuItems Nodes include Controls and Panes and several other subtypes as well Controls are user interface objects Buttons, TextFields, Labels, and so on Panes are layout objects for arranging the controls
JavaFX Node Hierarchy (part) Controls are buttons and fields and so on Canvas MediaView Group Control Parent Region A Node containing other Nodes Node Pane Circle Panes are used to lay out controls Line Rectangle Shape Text Not to be confused with a Label
JavaFX Control Hierarchy (part) MenuBar TextInputControl TextField Control Label PasswordField Labelled ButtonBase Button CheckBox RadioButton ToggleButton
JavaFX Pane Hierarchy (part) BorderPane FlowPane Pane GridPane HBox StackPane VBox
JavaFX Controls and Panes Controls are Nodes the user can manipulate buttons, text fields, labels, choice boxes, … Panes are used to arrange the Controls inside the window border layout, grid layout, horizontal and vertical boxes Create Controls then add them to a Pane create nested Panes for finer layout
Our Controls Labels TextFields Buttons Label instructions = new Label("Enter numbers:"); specify the text for the label TextFields TextField num1Field = new TextField("0"); optionally specify contents of field Buttons Button addButton = new Button("Add"); specify label on button
Control Methods Can set the font on any of our controls let’s make a 24 point version of the default font instructions.setFont(new Font(24)); num1Field.setFont(new Font(24)); addButton.setFont(new Font(24)); Simplify by abstracting into methods: also create Font constant private Button makeMyButton(String text) { Button result = new Button(text); result.setFont(DEFAULT_FONT); return result; }
More Control Methods Set alignment on text fields private TextField makeMyField() { TextField result = new TextField("0"); result.setFont(DEFAULT_FONT); result.setAlignment(Pos.CENTER_RIGHT); resturn result; } Make result field un-editable TextField resultField = makeMyField(); resultField.setEditable(false);
Our Layout A GridPane lays items out in a grid rows and columns GridPane root = new GridPane(); Can set properties on the grid GridPane operations gaps between rows and columns root.setHgap(8); root.setVgap(8); gap between cells and edges root.setPadding(new Insets(5));
Adding Controls to the Pane For a GridPane say what and where to add root.add(resultField, 1, 3); columns come first so that’s column 1, row 3 columns and rows numbered from 0 Can spread a control over rows/columns root.add(instructions, 0, 0, 2, 1); so that’s 2 columns and 1 row, starting at 0, 0
Inactive Window Current window looks OK Doesn’t do anything has all controls in correct positions numbers can be typed in Doesn’t do anything clicking add/done buttons is useless can just close the window Need our buttons to do things
Polymorphism: EventHandlers An EventHandler is an object that can handle events generated by Buttons and other things as well EventHandler is a data type, but not a class it’s an interface need a class that implements that interface create it yourself to do what you want one class per button
The EventHandler Interface Has only one method: public void handle(Event event); Done button exits program use Platform.exit() instead of System.exit(0) make class private to our application private class DoneHandler implements EventHandler<Event> { @Override public void handle(Event event) { Platform.exit(); }
Activating a Button Activate by setting onAction property doneButton.setOnAction(new DoneHandler()); When button is clicked, the new object’s handle method is called window closes and program ends Similarly for addButton: addButton.setOnAction(new AddHandler()); but we’ll come back to that later….
Anonymous EventHandlers Don’t actually need to name the class just create it where you need it doneButton.setOnAction( new EventHandler<Event>() { @Override public void handle(Event event) { Platform.exit(); } }); specify the interface it implements implement the method(s)
Lambda Expressions Even easier! setOnAction knows it needs an EventHandler EventHandler only has one method so only need parameter and method body doneButton.setOnAction((Event event) -> { Platform.exit(); }); and you don't even need to say the parameter type! doneButton.setOnAction(event -> {
Adding the Numbers Read and write from/to TextFields use getText and Integer.parseInt to read #s use setText and Integer.toString to show result addButton.setOnAction(event -> { int n1, n2, sum; n1 = Integer.parseInt(num1Field.getText()); n2 = Integer.parseInt(num2Field.getText()); sum = n1 + n2; resultField.setText(Integer.toString(sum)); });
Problem What if non-numbers entered in TextFields? parseInt can’t change them into numbers throws a NumberFormatException Exception is an object that represents an error that has occurred in the program need to catch that exception and deal with it
Dealing with the Exception Try to add the numbers; catch the exception addButton.setOnAction(event -> { try { int n1, n2, s; n1=Integer.parseInt(num1Field.getText()); n2=Integer.parseInt(num2Field.getText()); s = n1 + n2; resultField.setText(Integer.toString(s)); } catch (NumberFormatException nfe) { resultField.setText("##Error##"); } });
Sample Code Extensions Sample code also creates tool tips… words of explanation on hover Tooltip.install(num1Field, new Tooltip("Enter # here")); A private method for adding numbers takes the three fields as its arguments addButton.setOnAction(event -> addTheNumbers(num1Field, num2Field, resultField); );
Questions
Adding Keyboard Accellerators Press ctrl-f to go to first number field: scene.getAccelerators().put( new KeyCodeCombination( KeyCode.F, KeyCombination.SHORTCUT_DOWN), (Runnable) () -> { num1Field.requestFocus(); num1Field.selectAll(); }); Requires access to scene and num1Field make TextFields instance variables or instance constants must be done in constructor