Graphical User Interface GUI Programming I Lecture Objectives
Graphical User Interface (GUI) Programming I
Lecture Objectives • Understand the basic concepts of Graphical User Interfaces (GUIs) • Practice Basic GUI Programming in Java • Develop Basic GUI Applications • Study Layout Management and Managers for GUI Applications
Outline Graphical User Interfaces (GUIs) -- Overview -- Essential elements Containers -- Overview -- Examples Components -- Overview -- Examples Layout Managers -- Overview -- Examples
Graphical User Interface (GUI) • A Graphical User Interface (GUI) is one variety of user interface. • User interacts with objects on the screen (icons, buttons, scroll-bars, etc. ) via mouse clicks or keyboard actions. Downloading libcrypt. . . File Edit 40% Cancel Open Save As. . . Quit Ok Enter
GUI Popularity • Popularized in 1980 s by the Macintosh. • Now state of the practice, and not final word in UI • Intended to replace text-based "command line" and "function key" interfaces. • Despite similarities, GUIs are typically platform-specific (Windows 95/98/NT/1900, Mac. OS, X Windows look-andfeel standards). • Some graphical toolkits now provide cross-platform APIs. E. g. wx. Windows, GTK+, Java.
Java’s GUI Capabilities Java provides essentially two related toolkits for making GUIs: 1. The Abstract Windowing Toolkit ("AWT"), and 2. The Java Foundation Classes ("Swing") Swing is merely an expanded version of the AWT, and provides greater control and convenience.
Why Two Toolkits in Java? AWT, then JFC or "Swing" MFC and always "BSo. D" Well, it’s a long story. In short, JFC (swing) is Sun’s answer to Microsoft’s MFC--a detailed toolkit library.
Cautionary Note Java has two flavors of toolkits: 1. Swing. 2. AWT. It is not wise to mix AWT and Swing Components. For your first programs, stick with one toolkit (swing!!!). We’ll start off with AWT Components to show the basics. Then, we will switch to Swing Components. How do you tell them apart? Generally, but not always, Swing Components will have a "J" in front of the class name: AWT Swing Button JButton
Keep in Mind • We will program graphical elements in source code. § There are drag and drop systems (graphical integrated development environments (IDEs). • Java is designed to work across different platforms. § This poses special challenges!!! • As does the very nature of WIMP GUI’s (windows, icons, menus, and pointing device graphic user interface)
Steps to GUI Construction We will learn GUI creation in two steps: the "view", and then the "controls" or event handling. In Java, to create a GUI, you (1): • Specify a Container, using. . . • a Layout Manager to. . . • place Components and/or Containers of Components. . . on the screen as desired. 1. i. e. UI form and appearance TODAY LATER In Java, to make a GUI act as the interface for a program, you (2) i. e. UI interaction and behavior • Design human/computer dialog, using Listeners and component-generated events 2.
GUI Design & Creation There are three essential constructs in any GUI: Containers -- used to hold items (e. g. , the frame) File Edit Layout. Managers -- the hidden algorithm used to organize the widgets inside the container offset Components -- the widgets or interactors (e. g. , buttons) Help CLICK ME offset
GUI Basic Constructs The three basic constructs used in every GUI are: 1. Containers File Edit Help offset 2. Components CLICK ME 3. Layout. Managers offset
EP ST Containers Examples of Containers: AWT • Panel • Frame • Applet • Window Swing • JPanel • JFrame • JApplet • JWindow Note: Containment is not the same as inheritance extension. A Frame may contain buttons, buttons are not subclasses of Frame. 1 Containers are special components that may contain other components.
Containers (Cont’d) A Container is a class that extends from java. awt. Container Object As it turns out, the class "Container" is itself a Component Containers can have: Container • Layouts set on them (discussed later) • Other components or containers added to them.
Containers: An Example Let’s make a simple Frame. When working with GUIs, you often have to consult the API. Note the inheritance structure of your classes.
Containers: An Example (Cont’d) So far, we’ve used the API to learn how to make a Frame. We found constructors for: public Frame (); public Frame (String str. Title); Now, how can we set the size of the Frame? We again return to the API.
Containers: An Example (Cont’d) The class java. awt. Frame does not contain a method to set its size. But such a method was inherited from java. awt. Component:
Containers: An Example (Cont’d) Likewise, there’s no method in java. awt. Frame to make the Frame visible. Instead, we find the method "show()" was inherited from java. awt. Window
Hello GUI – The Program import java. awt. *; public class Hello. GUI { public static void main (String[ ] arg) { System. out. println("About to make GUI"); Frame f = new Frame ("Hello GUIs"); f. set. Size( 200, 200 ); f. show(); System. out. println("Finished making GUI"); } // main() } // class Hello. GUI
Hello GUI – The Program (Cont’d) Our program runs, and the frame never goes away. When we reach the end of main (as our print statement indicates) why doesn’t the program end?
Hello GUI – The Program (Cont’d) When the Java VM created our Frame, it entered into a kind of ‘infinite loop’, waiting for input and events. (This is common for all graphical toolkits. ) import java. awt. *; public class Hello. GUI { public static void main (String[ ] arg) { System. out. println ("About to make GUI"); Frame f = new Frame ("Hello GUIs"); f. set. Size( 200, 200 ); f. show(); System. out. println ("Finished making GUI"); }// main }// class Hello. GUI while(true){ //get user input // handle event } Since we didn’t write any event handlers, not even the "window disposal" button will work.
Hello GUI – The Program (Cont’d) Solution: To fix this problem, we’ll have to write some event handling code. But in order to write some event handling code, we have to create some components… So, for now, you’ll just have to use Ctrl-C to end the program. Once the basics of GUI construction are covered, we’ll return to this problem.
GUI Design Idea We really have two choices when working with top-level containers: 1. Inheritance -- our class extends a container java. awt. Frame My. GUI 2. Composition -- our class holds a container My. GUI java. awt. Frame
GUI Design Idea: Example We save our single inheritance import java. awt. *; public class Hello. Composition { Frame f; public Hello. Composition() { f = new Frame("Composition Test"); f. set. Size(200, 200); f. set. Background(Color. red); f. show(); Check the API } public static void main(String[] args) { Hello. Composition h = new Hello. Composition(); } } Will call constructor, so the show() method gets called
GUI Design Idea: Example A few changes allows us to convert between the two solutions: import java. awt. *; public class Hello. Inheritance extends Frame { Frame f; public Hello. Inheritance(){ f = new Frame super("Composition Test"); f this. set. Size(200, 200); f this. set. Background (Color. red); f this. show(); } public static void main (String[] args) { Hello. Inheritance h = new Hello. Inheritance(); } } Note: Even the statement this. could be safely removed!
Which Solution Works Better? Inheritance Composition • Use up our single inheritance • Saves the single inheritance • "Wasted inheritance" occurs where we subclass, but fail to override anything. • Useful when you want the "factory settings" for a GUI, with no changed behavior • Easier to change basic GUI behavior • Often requires more code, more references
Container Summary • Creating containers requires careful study of the API. Watch the inheritance structure of the classes. • A top-level container, like a Frame, requires event handlers (covered later). • There are many useful methods for customizing containers. Just look them up in the API documentation: my. Frame. set. Background(Color. red); An inherited method A class, also in the API
Container Summary We may often use "composition" where: -- We don’t anticipate changing behaviors -- We need to save our single inheritance We may often use "inheritance" where: -- We need to change basic GUI behaviors
EP ST Components 2 Most interactions in a Java GUI are with Components. • Another generic term for Component in other GUIs (e. g. X Windows) is "widget". • Different types of components for different types of interaction (e. g. buttons, etc. ) User interactions with components create events (thus, allow event-driven programming) As a rule, a Component cannot have other components inside: • Exceptions to rule: pop up menus may have menu items added to them. And Containers are themselves components due to inheritance.
Component Examples Demo: Hello. Widget
Component Examples (Cont’d) Component Recall: A Container "is a" Component - generic widget that you can interact with Button - a widget that you can press Canvas - a widget that you can draw on Checkbox - a widget that is checked or not checked Choice - an option menu that drops down Container - a generic class that contains Components Panel - a Container to be used inside another container; used to split an existing window Label - a single line of read-only text List - a list of Strings Scrollbar - a horizontal or vertical scrollbar Text. Component Text. Area - multi-line editable text Text. Field - single-line editable text
Component Examples (Cont’d) Canvas: • Typically a drawing surface on which shapes, graphs, pictures, etc can be drawn. • Utilize mouse events and mouse motion events to interact with the user to accomplish the drawing tasks. Text. Field: • A one-line data entry area. • Theoretically infinite in length. • Can generate Key events to indicate that the user has typed a key. • More typically, it generates an Action event when the user finishes the data entry and hits Return in the Text. Field.
Component Examples (Cont’d) Button: • Simply a clickable component. • Appears as a standard button on whatever graphical environment the user happens to be running at the time. • Generates an Action event when clicked. Label: • A one-line field of text. • User cannot change this text directly; program changes text with set. Text( ) method. • Usually not used to capture events (but could). • Usually used as a one-way information source to provide a message to the user.
Joining Components & Containers have a method: public void add (Component c) that allows us to place items inside. Thus: Panel p = new Panel(); Button b 1 = new Button ("Example 1"); Button b 2 = new Button ("Example 2"); p. add (b 1); p. add(b 2); In this example, two buttons are added to the panel.
An Example import java. awt. *; public class Hello. Component { Frame f; public Hello. Component(){ f = new Frame("Component Test"); f. set. Size(200, 200); f. set. Background(Color. red); Panel p = new Panel(); Button b = new Button("Hello Components"); p. add(b); f. add(p); f. show(); } public static void main (String[] args) { new Hello. Component(); } }
3 We can now create Components and Containers. EP ST Layout Managers But how can they be organized? We might be tempted to call methods that set the x, y location of a component in a container. Consulting the API, we find some likely methods: public void set. Location(int x, int y); public void set. Size(int width, int height);
Layout Managers: Motivation • To arrange items, one could specify the location of a Component by specific x and y coordinates. The Component class contains the method set. Location(int width, int height): Frame f = new Frame(); What’s f. set. Size(500, 500); wrong Button my. Button = new Button ("Click"); with this add(my. Button); approach? ? ? my. Button. set. Location(25, 75); 75 pixels down NOTE: Origin 0, 0 at top left! Click Note: Button’s x and y coordinate starts from top left 25 pixels over
Layout Managers: Motivation (Cont’d) Problems with specifying (x, y) coordinates for Components: • This becomes tedious for even mildly complex GUIs. • Addition of more components requires recalculation of every component’s x, y coordinate. • If container resizes (e. g. , user expands window), calculations have to be redone! Solution: • Position components based on a percentage of available container size. Or create an algorithm to place components. . . But Java already does this for you !!!
Layout Managers: AWT-Based • Java provides several layout managers. • We will concentrate here on several of them: • Border. Layout • Grid. Layout • Flow. Layout • Box. Layout • To tell a container which layout manager to use, invoke the metho set. Layout( ); and specify a type of layout. For example: To specify a Border. Layout: set. Layout (new Border. Layout());
Layout Managers: Two General Flavors • One can conceptually divide layout managers into two types: § Those that attach constraints to their components. § Those that do not. • What does this mean, "attach constraints“? If a manager attaches constraints to a component, then information about a component’s location (e. g. , compass points) is stored with the object.
Layout Managers: Constraints • Border. Layout specifies constraints corresponding to compass regions of a container: NORTH WEST CENTER SOUTH EAST
Layout Managers: Constraints (Cont’d) • Border. Layout then appends constraint information on all components, e. g. : this. set. Layout (new Border. Layout()); Button e = new Button ("East"); Button w = new Button ("West"); Button n = new Button ("North"); add(e, "East"); // deprecated add("West", w); // works; deprecated add(n, Border. Layout. NORTH); // preferred
Layout Managers: Constraints (Cont’d)
Layout Managers: Another Example import java. awt. *; public class Test extends Frame { public Test() { super ("Border. Layout Demo"); this. set. Size(200, 200); this. set. Layout(new Border. Layout()); this. add (new Button ("North"), Border. Layout. NORTH); this. add (new Button ("South"), Border. Layout. SOUTH); this. add (new Button ("East"), Border. Layout. EAST); this. add (new Button ("West"), Border. Layout. WEST); this. add (new Button ("Center"), Border. Layout. CENTER); } public static void main (String[ ] args) { new Test(). show(); } } // Test
Layout Managers: Another Example (Cont’d) Program Output:
Border. Layout specifies the arrangement: CENTER EAST WEST NORTH SOUTH • To add components to a Border. Layout, specify the position in which the component will reside. • Only one component (or container) can go in each of the five positions.
Border. Layout: An Example set. Layout (new Border. Layout()); add(new Label ("Hello!"), "North"); Canvas my. Canvas = new Canvas(); // more about Canvas in a moment add (my. Canvas, "Center"); Hello! { a fresh canvas for drawing here}
Border. Layout: Simple Example import java. awt. *; public class Hello. Layout { public static void main(String[] args) { Frame f = new Frame(); f. set. Size(400, 400); Border. Layout bord = new Border. Layout(); f. set. Layout(bord); Button b = new Button ("Hello"); f. add(b, Border. Layout. SOUTH); } } // Hello. Layout Will this work? Let’s run it and find out. . .
Border. Layout: Simple Example (Cont’d) import java. awt. *; public class Hello. Layout { public static void main(String[] args) { Frame f = new Frame(); f. set. Size(400, 400); Border. Layout bord = new Border. Layout(); f. set. Layout(bord); Button b = new Button ("Hello"); f. add(b, Border. Layout. SOUTH); f. show(); } } // Hello. Layout Ahh. . We forgot to set our Frame visible. Now it works. Welcome to the exciting world of GUI debugging.
Layout Managers: No Constraints • The second type of Layout. Manager does not specify constraints for the objects it holds. • Examples: § Grid. Layout() § Flow. Layout() • Without constraints, you cannot accurately predict layout behavior across platforms.
Layout Managers: No Constraints (Cont’d) import java. awt. *; public class Flow. Test extends Frame { String Labels[] = {"Short", "Long Label", "Really, really long"}; public Flow. Test(){ this. set. Size(400, 200); set. Layout(new Flow. Layout()); for (int i = 0; i < Labels. length; i++){ Button temp = new Button (Labels[i]); add (temp); } } public static void main (String arg[]){ new Flow. Test(). show(); } } //class Flow. Test
Layout Managers: No Constraints (Cont’d) Program Output:
Layout Managers: No Constraints (Cont’d) Program Output is also:
Layout Managers: No Constraints (Cont’d) Note: § Since pixels, fonts and insets vary with each platform, layout without constraints will vary greatly. Lesson: § Use layout managers without constraints only when you have few components, or you’ve anticipated their possible movement.
Layout Managers: No Constraints (Cont’d) • Don’t think that layout managers without constraints are not useful! • One of the most useful constraint-free layout manager is "Grid. Layout". public Grid. Layout(); public Grid. Layout(int rows, int cols, int hgap, int vgap);
Grid. Layout specifies a grid pattern via: set. Layout (new Grid. Layout (rows, columns)); For example: set. Layout (new Grid. Layout(2, 3)); generates:
Grid. Layout (Cont’d) • To add components (or containers) to a Grid. Layout, particular locations are not specified (unlike Border. Layout). • Instead, the components (or containers) are positioned by the sequence in which they are added, as indicated by numerals below. • Significantly, Grid. Layout is distortive, meaning components are stretched to fill the available space in the grid. 1 4 2 3 5 6
Grid. Layout (Cont’d) Optionally, two additional parameters may be used with Grid. Layout to specify the horizontal and vertical spacing (in pixels) between grid elements: set. Layout (new Grid. Layout (rows, columns, hspace, vspace)); where hspace specifies horizontal size, and vspace specifies vertical size e. g. , set. Layout (new Grid. Layout (2, 2, 7, 5)); hspace vspace
Grid. Layout: Example 1 import java. awt. *; public class Calc. Pad extends Frame { public Calc. Pad() { set. Layout(new Grid. Layout(5, 3)); add (new Button ("7")); public static void main (String[] args){ add (new Button ("8")); Calc. Pad ti = new Calc. Pad(); add (new Button ("9")); ti. set. Size(150, 150); add (new Button ("4")); add (new Button ("5")); add (new Button ("6")); add (new Button ("1")); add (new Button ("2")); add (new Button ("3")); add (new Button ("0")); add (new Button ("+/-")); add (new Panel()); } ti. show(); } }//Calc. Pad Program Output:
Grid. Layout: Example 2 import java. awt. *; public class Calc. Pad extends Frame { public Calc. Pad() { set. Layout(new Grid. Layout(5, 3)); int off[]={-2, 2, 0}; for (int i=9; i >= 1; i--) add (new Button (""+(i+off[i%3]))); add (new Button (". ")); add (new Button ("0")); add (new Button ("+/-")); add (new Panel()); } public static void main (String[] arg){ Calc. Pad ti = new Calc. Pad(); ti. set. Size(150, 150); ti. show(); } }//Calc. Pad Program Output:
Box. Layout: Motivation Often, it is desirable to place items in horizontal or vertical direction. A grid layout may not be the best choice, since grid components are resized to fit the available space--it’s a distorts its contents. container component Desired look A (3, 1) grid forces size changes
Box. Layout Manager A Box. Layout provides this feature. It resembles a Flow. Layout, but with directional control, and other features. Horizontal and vertical flow control
Box. Layout: How? The Box. Layout has a single constructor: Box. Layout(Container target, int axis); The ‘target’ is the container we wish to layout. The ‘axis’ is a static field: Box. Layout. X_AXIS; Box. Layout. Y_AXIS; JPanel button. Panel = new JPanel(); Box. Layout b. Layout = new Box. Layout (button. Panel, Box. Layout. X_AXIS); button. Panel. set. Layout(b. Layout);
- Slides: 63