JAVA Graphical User Interfaces Objectives Be able to

JAVA Graphical User Interfaces

Objectives • Be able to use Java Foundation Class (JFC) Swing components JFrame, JButton, JText. Field, and JLabel • Be able to choose and use an appropriate layout manager • Be able to use JPanel to create structured layouts • Be able to implement interaction using events and listeners • Be able to encapsulate a processing program within a Java GUI.

3 Java GUI Programming and Design • Graphical user interfaces (GUIs) are a standard application for object-oriented programming. • If the user can’t figure the interface out, it doesn’t matter how good the program is. • An interface must be usable: • Include the information users need; leave out the information they • • don’t need. Be consistent from one window to another. Use commonly known interface patterns. Give feedback. Put the user in control.

4 Java Foundation Classes • The Java Foundation Classes (JFC) Swing library provides a library of classes for GUI implementation. • The most useful for us will be those for: • JFrame • JButton • JLabel • JText. Field • JPanel

Inheritance (Foreshadowing Ch 13) • A means of adding functionality to a class • Avoids repetitive programming • Shows relationships between classes • Implemented using the extends keyword • <child class> extends <parent class> • When using inheritance, the child class “gets” the data and methods of the parent

6 Building a GUI Controller • All Java GUIs are built using “frames”. • To build a GUI: • import the JFrame class from javax. swing • inherit from the JFrame class using extends • include a main() method • The main method implements the following algorithm: 1. Construct the frame object; 2. Set the frame as visible.

A basic GUI window import javax. swing. JFrame; public class Frame. Example extends JFrame { public Frame. Example(){ set. Title(“My. Frame”); set. Size(400, 300); set. Default. Close. Operation(EXIT_ON_CLOSE); } public static void main(String[] args) { Frame. Example frame = new Frame. Example(); frame. set. Visible(true); // display the frame } }

Adding Components • Use appropriate constructor: • JButton ok. Button = new JButton(“Ok”); • JText. Field name. Field = new JText. Field(“Type your name”); • JLabel message = new JLabel(“Welcome to my program!”); • Add new component to the frame (within constructor): add(ok. Button); add(name. Field); add(message); • Default location to place an added component is the center of the screen!

10 Layout Managers • Java provides a variety of layout managers that pack components in a GUI frame. • Border. Layout() – components added at compass positions (north, south, east, west, center); • Flow. Layout() – components are added left-to-right, top-to -bottom; • Box. Layout() – components added in horizontal or vertical box; • Grid. Layout(m, n) – components are added on a grid of m n equal sized cells (m rows, n columns); • Grid. Bag. Layout – The most flexible (and complicated) layout manager.

11 import java. awt. Border. Layout; import javax. swing. *; public class Border. Window extends JFrame { public Border. Window(){ set. Title("Border. Layout"); set. Default. Close. Operation(EXIT_ON_CLOSE); // set. Layout(new Border. Layout()); This is actually the default. add(new JButton("Button 1 (NORTH)"), Border. Layout. NORTH); add(new JButton("2 (CENTER)"), Border. Layout. CENTER); add(new JButton("Button 3 (WEST)"), Border. Layout. WEST); add(new JButton("Long-Named Button 4 (SOUTH)"), Border. Layout. SOUTH); add(new JButton("Button 5 (EAST)"), Border. Layout. EAST); } public static void main(String args[]) { Border. Window bw = new Border. Window(); bw. pack(); bw. set. Visible(true); } }

12 import java. awt. Flow. Layout; import javax. swing. JButton; import javax. swing. JFrame; public class Flow. Window extend JFrame { public Flow. Window(){ set. Title("Flow. Layout"); set. Default. Close. Operation(EXIT_ON_CLOSE); set. Layout(new Flow. Layout()); add(new JButton("Button 1")); add(new JButton("2")); add(new JButton("Button 3")); add(new JButton("Long-Named Button 4")); add(new JButton("Button 5")); } public static void main(String args[]) { Flow. Window fw = new Flow. Window(); fw. pack(); fw. set. Visible(true); } }


What about more structure?

Grouping Components: JPanel • A JPanel can group user-interface components • Each JPanel can have its own layout • JPanels can have JButtons, JText. Fields etc. • Must be added to the frame!

Using JPanel // Message and textfield as before … //Create panel and buttons JPanel button. Panel = new JPanel(new Flow. Layout()); JButton ok. Button 1 = new JButton("Ok"); JButton ok. Button 2 = new JButton("Okidokie"); JButton ok. Button 3 = new JButton("Okay"); //Put buttons onto JPanel button. Panel. add(ok. Button 1); button. Panel. add(ok. Button 2); button. Panel. add(ok. Button 3); //add group of buttons to frame add(button. Panel, Border. Layout. SOUTH);

import javax. swing. *; import java. awt. Border. Layout; import java. awt. Grid. Layout; public class Phone. Dialer extends JFrame { public Phone. Dialer (){ set. Title(“Phone Dialer”); set. Default. Close. Operation(EXIT_ON_CLOSE); add(new JText. Field("Number dialed will appear here"), Border. Layout. NORTH); //keypad holds the additional structure of the number buttons JPanel keypad = new JPanel(); keypad. set. Layout(new Grid. Layout(4, 3)); for (int i = 1; i<10; i++){ keypad. add(new JButton("" + i)); } keypad. add(new JLabel("")); keypad. add(new JButton("0")); add(keypad, Border. Layout. CENTER); //must add keypad to the frame add(new JButton("Phone"), Border. Layout. SOUTH); } public static void main(String[] args) { Phone. Dialer dialer = new Phone. Dialer(); dialer. pack(); dialer. set. Visible(true); } }

Events and Listeners • An event is a signal to the program that something has happened • GUI components can trigger events (e. g. JButtons, JText. Fields, JSlider, JCheck. Box, etc. ) • When triggered, an appropriate event object is created • JButton and JText. Fields generate events of type Action. Event • A listener is an object interested in an event • Must be an instance of a listener interface • An interface specifies a set of methods that an implementing class must implement. • Must be registered with a source component (i. e. registered with an object that generates events e. g. JButton)

19 Action Listeners • Listener objects are defined as classes that: • Implement the Action. Listener interface; • Override the action. Performed() method. • GUI objects that generate events must register an action listener. gui. Object. add. Action. Listener(act. List. Object)

Using Action. Listener • Define a class to act as the listener: class Button. Listener implements Action. Listener{ public void action. Performed(Action. Event e) { //do whatever should happen when button pushed } } • Construct an instance of the class and add it as the listener for an object that will generate an event: JButton my. Button = new JButton(“Click me!”); my. Button. add. Action. Listener(new Button. Listener());

Handling Multiple Actions • Most GUIs have multiple widgets that might cause action events to be generated • Construct and register a different listener for each event using an inner class • A class defined inside of another class • Usually very short – our inner classes will only define the action. Performed method • Example on next slide

. . . // import statements for Swing components and actions public class Which. Button extends JFrame { public Which. Button() {. . . // code as before my. Left = new JButton("Left"); my. Left. add. Action. Listener(new Left. Button. Listener()); add(my. Left); my. Right = new JButton("Right"); my. Right. add. Action. Listener(new Right. Button. Listener()); add(my. Right); } class Left. Button. Listener implements Action. Listener{ public void action. Performed(Action. Event e) { my. Indication. set. Text("Left"); } } class Right. Button. Listener implements Action. Listener{ public void action. Performed(Action. Event e){ my. Indication. set. Text("Right"); } } //other code including main method }

One Action Listener Object • If only one listener is required we can use the controller object: public class Example extends Jframe implements Action. Listener{ • Then, we add an action listener using “this”: public Click. Button(){. . . // setting up the frame my. Button = new JButton(“Button”); my. Button. add. Action. Listener(this); add(my. Button); . . . } • Must define an action. Performed method: public void action. Performed(Action. Event e) { my. Message. set. Text(”Button was pressed"); my. Button. set. Enabled(false); }

24 More JFC • The Swing GUI classes provide a variety of other GUI components. • The GUI slider component, for example is implemented using Change. Listener and the state. Changed() method. • Java provides good reference and tutorial materials for JFC and Swing, e. g. : http: //java. sun. com/docs/books/tutorial/ui/features/components. html

25 Integrating Processing & Java • You can integrate a Processing sketch into a Java GUI as follows: • Encapsulate the Processing sketch as an object that inherits from PApplet; • Construct that object and add it to the GUI controller frame

26 Encapsulating a Sketch • Processing sketches are implemented as classes that inherit from PApplet. • You can encapsulate sketches as follows: 1. Create a new class that extends PApplet and contains the Processing sketch code; 2. Mark the pre-defined Processing methods (e. g. , setup() and draw() ) as public; 3. Treat the sketch variables as instance data and add constructors, accessors and mutators as needed.

27 package c 08 java. shaker; import processing. core. PApplet; /** * Shaker. Panel 1 is a simple Java encapsulation of a shaker animation from Processing. * It draws a shaking circle and allows the user to reposition the circle using a mouse click. * * @author kvlinden * @version Fall, 2009 */ public class Shaker. Panel extends PApplet { private static final int SIZE = 300; private int my. Shift; public Shaker. Panel(int shift) { my. X = my. Y = SIZE / 2; my. Shift = shift; } public void setup() { size(SIZE, SIZE); smooth(); } public void draw() { background(255); stroke. Weight(2); ellipse(my. X + random(-my. Shift / 2, my. Shift / 2), my. Y + random(-my. Shift / 2, my. Shift / 2), 50); } public void mouse. Pressed() { my. X = mouse. X; my. Y = mouse. Y; } }

28 package c 08 java. shaker; import javax. swing. JFrame; /** * Shaker. Controller 1 is a simple version of a Java controller for the Processing shaking circle * application. It provides a simple Jframe in which to run the original application as it runs * in Processing. * * @author kvlinden * @version Fall, 2009 */ public class Shaker. Controller extends JFrame { private Shaker. Panel my. Shaker. Panel; public Shaker. Controller() { set. Title("Shaker 1"); set. Default. Close. Operation(EXIT_ON_CLOSE); my. Shaker. Panel = new Shaker. Panel(5); my. Shaker. Panel. init(); add(my. Shaker. Panel); } public static void main(String[] args) { Shaker. Controller controller = new Shaker. Controller(); controller. pack(); controller. set. Visible(true); } }

Interacting with an encapsulated Processing sketch • The controller object (which extends JFrame) has an object (i. e. an instantiation) of the PApplet class • Use accessors, mutators and utility methods of the PApplet object to make changes happen from the controller

30 public class Shaker. Controller extends JFrame { private Shaker. Panel my. Shaker. Panel; private JText. Field my. Shift. Field; private JButton my. Start. Button, my. Pause. Button; public Shaker. Controller() { set. Title("Shaker"); set. Default. Close. Operation(EXIT_ON_CLOSE); set. Layout(new Border. Layout()); my. Shaker. Panel = new Shaker. Panel(); my. Shaker. Panel. init(); add(my. Shaker. Panel, Border. Layout. NORTH); // a control panel JPanel control. Panel = new JPanel(new Flow. Layout()); my. Start. Button = new JButton("Start"); my. Start. Button. set. Enabled (false); my. Start. Button. add. Action. Listener (new Start. Button. Listener()); control. Panel. add(my. Start. Button); my. Pause. Button = new JButton("Pause"); my. Pause. Button. set. Enabled (true); my. Pause. Button. add. Action. Listener (new Pause. Button. Listener()); control. Panel. add(my. Pause. Button); control. Panel. add(new JLabel("Shift factor: ")); my. Shift. Field = new JText. Field(3); my. Shift. Field. set. Text(String. format("%d", my. Shaker. Panel. get. Shift())); control. Panel. add(my. Shift. Field); my. Shift. Field. add. Action. Listener (new Shift. Field. Listener()); add(control. Panel, Border. Layout. CENTER); } // continued on next slide

31 // continued from previous slide class Start. Button. Listener implements Action. Listener { @Override public void action. Performed(Action. Event ae) { my. Shaker. Panel. set. Running (true); my. Start. Button. set. Enabled (false); my. Pause. Button. set. Enabled (true); } } class Pause. Button. Listener implements Action. Listener { @Override public void action. Performed(Action. Event ae) { my. Shaker. Panel. set. Running (false); my. Start. Button. set. Enabled (true); my. Pause. Button. set. Enabled (false); } } class Shift. Field. Listener implements Action. Listener { @Override public void action. Performed(Action. Event ae) { try { my. Shaker. Panel. set. Shift (Integer. parse. Int(my. Shift. Field. get. Text())); } catch (Exception e) { my. Shift. Field. set. Text(“Invalid shift value. Please try again. ”); } } } public static void main(String[] args) { Shaker. Controller controller = new Shaker. Controller(); controller. pack(); controller. set. Visible(true); } } // closes Shaker. Controller class declaration

} public void set. Running(boolean status) { my. Running. Status = status; } public void set. Shift(int shift) throws Exception { if (shift < 0) { throw new Exception("invalid shift value: " + shift); } my. Shift = shift; } public int get. Shift() { return my. Shift; } public void mouse. Pressed() { my. X = mouse. X; my. Y = mouse. Y; } public void draw() { if (my. Running. Status) { background(255); stroke. Weight(2); ellipse(my. X + random(-my. Shift / 2, my. Shift / 2), my. Y + random(-my. Shift / 2, my. Shift / 2), 50); } } public void setup() { size(SIZE, SIZE); smooth(); background(255); } //constructor public Shaker. Panel() { my. X = my. Y = SIZE / 2; my. Shift = 10; my. Running. Status = true; } private static final int SIZE = 300; private int my. X, my. Y, my. Shift; private boolean my. Running. Status; public class Shaker. Panel extends PApplet { 32

Review • To encapsulate a Processing sketch in a Java GUI: • Move Processing sketch to a new Java class that extends PApplet • Make animation methods public • Turn animation variables into instance variables • Write a constructor method that initializes any instance variables • In the controller class (that extends JFrame): • Create an instance of the new sketch class by calling the constructor • Call the init() method on the instance • Add the instance to the frame

34 Using Additional Classes • Only one class should handle the Processing animation • There should only ever be one class that extends PApplet!!! • Classes are best way to model additional features • So: • Support class extends Object (only); (this is implicit) • Pass a reference to the PApplet object to the render() method. +render()

35 public class Shaker. Panel extends PApplet { private int my. Size, my. X, my. Y, my. Shift; private boolean my. Running. Status; private Figure my. Figure; public Shaker. Panel(int size, int shift) { my. Size = size; my. Shift = shift; my. Running. Status = true; my. Figure = new Figure(my. Size / 2, 50, 5); } //. . . repeated code removed for space. . . public void setup() { size(my. Size, my. Size); smooth(); } public void draw() { if (my. Running. Status) { background(255); my. Figure. render(this); } } }

36 import processing. core. PApplet; public class Figure { private int my. X, my. Y, my. Diameter, my. Shift; public Figure(int x, int y, int diameter, int shift) { my. X = x; my. Y = y; my. Diameter = diameter; my. Shift = shift; } public void render(PApplet p) { p. stroke. Weight(2); p. ellipse(my. X + p. random(-my. Shift / 2, my. Shift / 2), my. Y + p. random(-my. Shift / 2, my. Shift / 2), my. Diameter); } }

Exercise • Expanding figure controller

38 Java. Doc • Application Programmers Interface (API) documentation is one critical aid in using a common abstraction. • Java. Doc is a Java tool designed to automate the construction of API documentation. What’s the Big Idea

39 Java. Doc: Comments • Java. Doc supports comments for classes, methods, instance variables. • Java. Doc comments include: • A general description of the component written in HTML; • Additional tagged information for: • @author • @version • @param • @return

40 Java. Doc: Example package c 08 java. text_examples; import java. util. Scanner; /** * Temperature. Converter converts Celsius temperatures to Fahrenheit. This * routine assumes that the user enters a valid temperature. * * @author kvlinden * @version 23 august 2009 */ public class Temperature. Converter { /** * This string prompt illustrates a static data member. */ public static final String PROMPT = "Please enter the temperature in Celsius: "; /** * The main method implements the temperature conversion using console-base input and output. * * @param args these command line arguments are ignored */ public static void main(String[] args) { System. out. print(PROMPT); Scanner keyboard = new Scanner(System. in); double celsius = keyboard. next. Double(); double fahrenheit = ((9. 0 / 5. 0) * celsius) + 32; System. out. print(celsius + " degrees Celsius is " + fahrenheit + " degrees Fahrenheit. n"); } }

41 Java. Doc: Generation
- Slides: 40