Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS102 – GUI Based on : David Davenport’s slides Spring 2002

Similar presentations


Presentation on theme: "CS102 – GUI Based on : David Davenport’s slides Spring 2002"— Presentation transcript:

1 CS102 – GUI Based on : David Davenport’s slides Spring 2002
References: Core Java Volume 1 AWT – components drawn using OS so not exactly the same on all systems Swing – drawn by Java so can be same everywhere!

2 AWT abstract window toolkit
AWT components were provided by the JDK 1.0 and 1.1 platforms. delegates into native windowing system therefore, looks different in different platforms

3 AWT Since platforms vary, AWT had to choose a lowest common denominator write once, debug everywhere …

4 JFC & Swing JFC is short for JavaTM Foundation Classes, which encompass a group of features to help people build graphical user interfaces (GUIs). The JFC was first announced at the 1997 JavaOne developer conference and has the following features: The Swing Components Include everything from buttons to split panes to tables. You can see mugshots of all the components in Pluggable Look and Feel Support Gives any program that uses Swing components a choice of looks and feels. For example, the same program can use either the JavaTM look and feel or the Windows look and feel. We expect many more look-and-feel packages to become available from various sources. Accessibility API Enables assistive technologies such as screen readers and Braille displays to get information from the user interface. Java 2DTM API (Java 2 Platform only) Enables developers to easily incorporate high-quality 2D graphics, text, and images in applications and in applets. Drag and Drop Support (Java 2 Platform only) Provides the ability to drag and drop between a Java application and a native application.

5 Swing is implemented without making use of native window elements
components are painted by java on blank windows. more flexibility, not the lowest common denominator same look, same bugs in all platforms The Swing components will continue to be enhanced in the future, AWT is dying

6 Swing, other differences
Swing buttons and labels can display images instead of, or in addition to, text. You can easily add or change the borders drawn around most Swing components. For example, it's easy to put a box around the outside of a container or label. You can change the behavior or appearance of a Swing component by either invoking methods on it or creating a subclass of it. Swing components don't have to be rectangular. Buttons, for example, can be round. Assistive technologies such as screen readers can easily get information from Swing components. For example, a tool can easily get the text that's displayed on a button or label.

7 CDE/Motif look and feel
Look & Feel                                                                         Java look and feel                                                                       CDE/Motif look and feel Windows look and feel

8 Swing’s Handicaps? performance familiarity

9 Programming forms Procedural programming Event-driven programming
code is executed in sequential order. Event-driven programming code is executed upon activation of events. statement 1 statement 2 statement 3 statement n method 1 method 2 method 3 method n Do method 2 then method 1 then method 3 Do method 1 then method 3

10 procedural programming
Up to now, our control flow model has been pretty straight-forward. Execution starts at main() and executes statement sequentially branching with if,for,and while statement, and occasional method calls. When we need user input we call read() on the console stream which waits (blocks) until the user types something, then returns. One problem with this model is: How do we wait for and respond to input from more than one source (eg keyboard and mouse). If we block on either waiting for input, we may miss input from the other.

11 Event-driven programming
the system waits for user input events, and these events trigger program methods Event-based programming addresses the two problems: How to wait on multiple input sources (input events) How to decide what to do on each type of input event

12 General form of event-driven programming
The operating system and window system process input event from devices (mouse movement, mouse clicks, key presses etc) The window system decides which window, and hence which frame and program, each input event belongs to. A data structure describing the event is produced and placed on an 'event queue'. Events are added to one end of the queue by the window system . Events are removed from the queue and processed by the program. These event data structures hold information including: Which of the program's windows this event belongs to. The type of event (mouse click, key press, etc.) Any event-specific data (mouse position, key code, etc.)

13 Event loop main(){ ...set up application data structures...
...set up GUI.... // enter event loop while(true){ Event e = get_event(); process_event(e); // event dispatch routine } } the event loop is usually hidden from programmer, he/she provides just a process_event() method

14 Java Event Management java system has more control over event system, it directs events based on their type you only override behavior you are interested in. more details later…

15 AWT Applications - Frame
Frame is a container for components Frame with normal window controls Optional Menu Three containers in Frame with Border Layout UI-components inside containers each with own layout

16 AWT classes AWTEvent Container Panel Applet Font Button Window Frame
FontMetrics Label Dialog FileDialog TextField Object Color TextComponent TextArea Graphics List Component Choice ScrollPane is another container CheckBox LayoutManager CheckBoxGroup Canvas MenuComponent MenuItem Menu Scrollbar MenuBar

17 AWT & Swing classes AWTEvent Fon t FontMetrics Object Color Panel
Classes in the java.awt package LayoutManager Heavyweight Fon t 1 FontMetrics Object Color Panel Applet JApplet Graphics Component Container Window Frame JFrame * Dialog JDialog JComponent Swing Components in the javax.swing package Lightweight

18 Swing - JComponents

19 Understanding the GUI UI-containers Each UI-component
have list of UI-components Each UI-component is a class with paint method & lists of Event listeners {Frame} {label} {textfield} {button} components System calls paint method whenever it needs to display on screen (as may be necessary when restoring minimised window or one previously covered by another window.) Painting is an example of polymorphism in action. Note: components generally repaint themselves when properties (such as text label or colour) changed, but if you are extending one, eg. Frame, then you may sometimes need to explicitly tell it to repaint itself.

20 Hint: Employ layout managers to arrange components in containers
Setting up the GUI Extend Frame class In constructor Create instances of containers & add them to Frame Create instances of components & add them to containers or Frame Possibly override paint method Hint: Employ layout managers to arrange components in containers UI-components added to components list Painting Frame paints Frame borders calls Frame paint method calls paint method of each object in component list

21 A simple example import javax.swing.*;
class FirstFrame extends JFrame { public FirstFrame() { setTitle("FirstFrame"); setSize(300, 200); } public class FirstTest { public static void main(String[] args) { JFrame frame = new FirstFrame(); frame.show();

22 Simple Example Remarks
we have two classes, one for the frame, the other for the main method that creates the frame we could have put the main method inside class FirstFrame if we don’t set the size, the default is a window of size 0x0 java runtime creates a new thread for our frame it doesn’t terminate, just hides

23 Hello World Program import javax.swing.*;
public class HelloWorldSwing { public static void main(String[] args) { JFrame frame = new JFrame("HelloWorld"); JLabel label = new JLabel("Hello World"); frame.getContentPane().add(label); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.setBounds(200, 200, 200, 50); frame.setVisible(true); }

24 Containers Swing provides three generally useful top-level container classes: JFrame, JDialog, and JApplet. To appear onscreen, every GUI component must be part of a containment hierarchy. Each containment hierarchy has a top-level container as its root. Each top-level container has a content pane that, generally speaking, contains the visible components in that top-level container's GUI. You can optionally add a menu bar to a top-level container. The menu bar is positioned within the top-level container, but outside the content pane.

25 Container Tree a frame, or main window (JFrame)
                                                                                            a frame, or main window (JFrame) a panel, sometimes called a pane (JPanel) a button (JButton) a label (JLabel)

26 Containers .. The frame is a top-level container. It exists mainly to provide a place for other Swing components to paint themselves. The panel is an intermediate container. Its only purpose is to simplify the positioning of the button and label. Other intermediate Swing containers, such as scroll panes (JScrollPane) and tabbed panes (JTabbedPane), typically play a more visible, interactive role in a program's GUI. The button and label are atomic components -- components that exist not to hold random Swing components, but as self-sufficient entities that present bits of information to the user. Often, atomic components also get input from the user.

27 Layouts

28 Using Layout Managers By default, every container has a layout manager. All JPanel objects use a FlowLayout by default, whereas content panes (the main containers in JApplet, JDialog, and JFrame objects) use BorderLayout by default. You can change the layout as: JPanel pane = new JPanel(); pane.setLayout(new BorderLayout()); When you add components to a panel or a content pane, the arguments you specify to the add method depend on the layout manager that the panel or content pane is using.

29 Border Layout A border layout lays out a container, arranging and resizing its components to fit in five regions: north, south, east, west, and center. Each region may contain no more than one component, and is identified by a corresponding constant: NORTH, SOUTH, EAST, WEST, and CENTER. When adding a component to a container with a border layout, use one of these five constants, for example: Panel p = new Panel(); p.setLayout(new BorderLayout()); p.add(new Button("Okay"), BorderLayout.SOUTH);

30 Border Layout Example Container contentPane = getContentPane();
//Use the content pane's default BorderLayout. //contentPane.setLayout(new BorderLayout()); contentPane.add(new JButton("Button 1 (NORTH)"), BorderLayout.NORTH); contentPane.add(new JButton("2 (CENTER)"), BorderLayout.CENTER); contentPane.add(new JButton("Button 3 (WEST)"), BorderLayout.WEST); contentPane.add(new JButton("Long-Named Button 4 (SOUTH)"), BorderLayout.SOUTH); contentPane.add(new JButton("Button 5 (EAST)"), BorderLayout.EAST);

31 Border Layout Output

32 Border Layout cont. We specified the component as the first argument to the add method. For example: add(component, BorderLayout.CENTER) //preferred However, you might see code in other programs that specifies the component second. For example, the following are alternate ways of writing the preceding code: add(BorderLayout.CENTER, component) add("Center", component) //valid but error prone By default, a BorderLayout puts no gap between the components it manages. You can specify gaps (in pixels) using the following constructor: BorderLayout(int horizontalGap, int verticalGap) You can also use the following methods to set the horizontal and vertical gaps, respectively: void setHgap(int) void setVgap(int)

33 BorderLayout(20, 20)

34 Border Layout Resizing
First North and South are drawn with their normal sizes, then east & west, finally all the rest of the space is reserved for center. center is the default location by default anything in center fill resize to fill the space

35 Border Layout Resized

36 Flow Layout FlowLayout puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, FlowLayout uses multiple rows. Within each row, components are centered (the default), left-aligned, or right-aligned as specified when the FlowLayout is created.

37 Flow Layout Example Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout()); contentPane.add(new JButton("Button 1")); contentPane.add(new JButton("2")); contentPane.add(new JButton("Button 3")); contentPane.add(new JButton("Long-Named Button 4")); contentPane.add(new JButton("Button 5"));

38 Flow Layout Example Output

39 The FlowLayout API The FlowLayout class has three constructors:
public FlowLayout() public FlowLayout(int alignment) public FlowLayout(int alignment, int horizontalGap, int verticalGap) The alignment argument must have the value FlowLayout.LEFT, FlowLayout.CENTER, or FlowLayout.RIGHT. The horizontalGap and verticalGap arguments specify the number of pixels to put between components. If you don't specify a gap value, FlowLayout uses 5 for the default gap value.

40 Grid Layout A GridLayout places components in a grid of cells.
Each component takes all the available space within its cell, and each cell is exactly the same size. If you resize the GridLayout window, it changes the cell size so that the cells are as large as possible, given the space available to the container.

41 Grid Layout Example Container contentPane = getContentPane();
contentPane.setLayout(new GridLayout(0,2)); contentPane.add(new JButton("Button 1")); contentPane.add(new JButton("2")); contentPane.add(new JButton("Button 3")); contentPane.add(new JButton("Long-Named Button 4")); contentPane.add(new JButton("Button 5")); The constructor tells the GridLayout class to create an instance that has two columns and as many rows as necessary.

42 Grid Output

43 The GridLayout API The GridLayout class has two constructors: public GridLayout(int rows, int columns) public GridLayout(int rows, int columns, int horizontalGap, int verticalGap) At least one of the rows and columns arguments must be nonzero. The horizontalGap and verticalGap arguments to the second constructor allow you to specify the number of pixels between cells. If you don't specify gaps, their values default to zero.

44 GridBagLayout GridBagLayout is the most flexible and complex one
A GridBagLayout places components in a grid of rows and columns, allowing specified components to span multiple rows or columns. Not all rows necessarily have the same height. Similarly, not all columns necessarily have the same width. Essentially, GridBagLayout places components in rectangles (cells) in a grid, and then uses the components' preferred sizes to determine how big the cells should be. see for a nice description

45 Setting Up … GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints(); JPanel pane = new JPanel(); pane.setLayout(gridbag); //For each component to be added to this container: //...Create the component... //...Set instance variables in the GridBagConstraints instance... gridbag.setConstraints(theComponent, c); pane.add(theComponent);

46 GridBagConstraints gridx, gridy
Specify the row and column at the upper left of the component. gridwidth, gridheight Specify the number of columns (for gridwidth) or rows (for gridheight) in the component's display area. fill Used when the component's display area is larger than the component's requested size to determine whether and how to resize the component. Valid values are NONE (the default), HORIZONTAL (make the component wide enough to fill its display area horizontally, but don't change its height), VERTICAL and BOTH. ipadx, ipady Specifies the internal padding: how much to add to the minimum size of the component. The default value is zero. The width of the component will be at least its minimum width plus ipadx*2 pixels, the height of the component will be at least its minimum height plus ipady*2 pixels. insets Specifies the external padding of the component -- the minimum amount of space between the component and the edges of its display area. By default, each component has no external padding. anchor Used when the component is smaller than its display area to determine where (within the area) to place the component. Valid values (defined as GridBagConstraints constants) are CENTER (the default), NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, and NORTHWEST. weightx, weighty Weights are used to determine how to distribute space among columns (weightx) and among rows (weighty); this is important for specifying resizing behavior.

47 GridBagLayout Example
All ipadx = 0 fill = HORIZONTAL Button 1 ipady = 0 weightx = 0.5 weighty = 0.0 gridwidth = 1 anchor = CENTER insets = new Insets(0,0,0,0) gridx = 0 gridy = 0 Button 2 weightx = 0.5 gridx = 1 gridy = 0 Button 3 weightx = 0.5 gridx = 2 gridy = 0 Button 4 ipady = 40 weightx = 0.0 gridwidth = 3 gridx = 0 gridy = 1 Button 5 ipady = 0 weightx = 0.0 weighty = 1.0 anchor = SOUTH insets = new Insets(10,0,0,0) gridwidth = 2 gridx = 1 gridy = 2

48 Horizontal Fill fill = HORIZONTAL expands components to maximum horizontally, but normal vertically fill=HORIZONTAL fill=NONE

49 Weights all the components expand equally horizontally, since their weightx are equal only button 5’s area expand vertically, since other’s weighty’s are 0

50 Ipad & inset ipad values grow the component itself, whereas insets grow the area while keeping the component same size fill = HORIZONTAL makes buttons wider than they should be, but only button 4 with a nonzero ipady value is higher than normal.

51 Why Layouts? Can use Absolute Layout
Layouts provide flexibility in different environments with different screen resolutions. Font sizes, component contents may change (internationalization)

52 Using Netbeans IDE

53 Events & Event Handling
Event listener object (executes method) Event Object Event cause (mouse, keyboard, timer, …) Event Source object Example… User clicks on a button Button is source of event object Event object passed to associated listener object Listener object executes associated method to perform desired task (save file, quit program, …)

54 Setting up Event Handling
Create listener class Using new or existing class, simply Implement desired event listener interface Putting code for desired action in its methods In application (e.g. Frame) Create instance of listener class Add as listener of source object can have any number of listeners for each event Source & listener can be same object!

55 Understanding Events When button is pressed Similarly for textfield
actionPerformed method of every item in button’s actionListeners list called Similarly for textfield When Frame close button is pressed windowClosing method of every item in Frame’s windowListeners list called {label} {Frame} components {textfield} WindowListeners Another example of polymorphism, this time using interfaces. Neat! windowClosing ActionListeners actionPerformed {MyListener} actionPerformed {button} ActionListeners

56 Event Classes ActionEvent ContainerEvent AdjustmentEvent FocusEvent
MouseEvent EventObject AWTEvent ComponentEvent InputEvent ItemEvent PaintEvent KeyEvent MouseEvent (pressed, released, entered, exited, clicked) & MouseMotionEvent (move, dragged) KeyPressed, KeyTyped & KeyReleased Events + million others! TextEvent WindowEvent ListSelectionEvent

57 Event Examples User clicks a button, presses Return while typing in a text field, or chooses a menu item ActionListener User closes a frame (main window)  WindowListener User presses a mouse button while the cursor is over a component  MouseListener User moves the mouse over a component  MouseMotionListener Component becomes visible  ComponentListener Component gets the keyboard focus  FocusListener Table or list selection changes  ListSelectionListener

58 How to Implement an Event Handler
In the declaration for the event handler class, specify that the class either implements a listener interface or extends a class that implements a listener interface. For example: public class MyClass implements ActionListener { Register an instance of the event handler class as a listener upon one or more components. For example: someComponent.addActionListener(instanceOfMyClass) Implement the methods in the listener interface. For example: public void actionPerformed(ActionEvent e) { ...//code that reacts to the action... }

59 public class MC extends JFrame implements ActionListener {
private int noClicks = 0; private JButton button = new JButton("click me !"); private JTextArea textArea = new JTextArea(5, 40); private JLabel label = new JLabel("Here you can see the number of button clicks") ; private JProgressBar progressBar = new JProgressBar(JProgressBar.HORIZONTAL); public MC(String title) { super(title); Container cp = getContentPane(); cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS)); cp.add(button); JScrollPane scrollPane = new JScrollPane(textArea); cp.add(scrollPane);cp.add(label); cp.add(progressBar); button.addActionListener(this); }

60 Action Example Cont. public void actionPerformed(ActionEvent e) {
noClicks++; textArea.append("Button clicked " + noClicks + " times so far \n"); label.setText("You clicked " + noClicks + " times"); progressBar.setValue(noClicks); } public static void main(String[] args) { MyClass frame = new MyClass("Simple Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.show();

61 Listener Class Flavors
public class MyClass implements MouseListener { ... someObject.addMouseListener(this); ... public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { ...//Event handler implementation goes here... } }

62 Adapter Classes Java comes with a variety of adapter classes that implement Listener interfaces but have empty implementations. One can extend an adapter class and only override events that are of interest

63 Adapter Example An example of extending an adapter class instead of directly implementing a listener interface. public class MyClass extends MouseAdapter { ... x.addMouseListener(this); ... public void mouseClicked(MouseEvent e) { //Event handler implementation // goes here... } }

64 Using an Inner class … What if your class has to extend another one?
public class MyClass extends Applet { ... x.addMouseListener(new MyAdapter()); ... class MyAdapter extends MouseAdapter { public void mouseClicked(MouseEvent e) { ...//Event handler implementation // goes here... }

65 Using an Anonymous Inner class
public class MyClass extends Applet { ... x.addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e) { //Event handler impl. } }); ... } } an inner class can refer to instance variables and methods just as if its code is in the containing class

66 Example class PanelJ2 extends JPanel { public PanelJ2() {
JButton b = new JButton( "OK"); setLayout( new BorderLayout() ); setBackground( Color.red); add( b, BorderLayout.SOUTH); b.addActionListener( new ExampleActionListener()); } // restores screen after window has been covered, minimized, public void paintComponent( Graphics g) { super.paintComponent( g); g.drawRect( 50, 50, 200, 100); g.drawString( "Hello", 125, 100 );

67 Action Listener class ExampleActionListener implements ActionListener { public void actionPerformed( ActionEvent e) { System.out.println( "Button Pressed"); }

68 Putting 3 of PanelJ2 … class MyJFrame extends JFrame {
public MyJFrame() { Container c = getContentPane(); c.setLayout( new FlowLayout() ); c.add( new PanelJ2()); setTitle( "ExampleJ3 - Hi there"); setBounds( 100, 150, 300, 300); setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); setVisible(true); }

69 Outcome …

70 Put them inside an applet
public class AppletExample extends Applet { public void init() { setLayout( new FlowLayout() ); add( new PanelJ2()); }

71 Applet outcome

72 Which button ? Let’s say you have three buttons on your application. How can you tell which button was pressed? We need something distinct about the event object to decide what to do We can use getSource() method

73 ButtonPanel class ButtonPanel extends JPanel implemnts ActionListener{
public ButtonPanel() {  yellowButton = new JButton("Yellow");       blueButton = new JButton("Blue");       redButton = new JButton("Red");        add(yellowButton);       add(blueButton);       add(redButton);        yellowButton.addActionListener(this);       blueButton.addActionListener(this);       redButton.addActionListener(this);    }     private JButton yellowButton, blueButton, redButton;

74 actionPerformed method
   public void actionPerformed(ActionEvent evt){  Object source = evt.getSource();       Color color = getBackground();       if (source == yellowButton) color = Color.yellow;       else if (source == blueButton) color = Color.blue;       else if (source == redButton) color = Color.red;       setBackground(color);       repaint();    } 

75 An alternative? We used the same listener object for all the buttons (ButtonPanel itself) Another approach would be to use different listeners who knows about what they should do when the event happens

76 ColorAction inner class
private class ColorAction implements ActionListener { public ColorAction(Color c) { backgroundColor = c; } public void actionPerformed(ActionEvent event) { setBackground(backgroundColor); private Color backgroundColor;

77 New constructor … public ButtonPanel() { // create buttons
JButton yellowButton = new JButton("Yellow"); . . . // add buttons to panel add(yellowButton); add(blueButton); add(redButton); // create button actions ColorAction yellowAction = new ColorAction(Color.YELLOW); ColorAction blueAction = new ColorAction(Color.BLUE); ColorAction redAction = new ColorAction(Color.RED); // associate actions with buttons yellowButton.addActionListener(yellowAction); blueButton.addActionListener(blueAction); redButton.addActionListener(redAction); }

78 ColorAction, another aproach
class ColorAction implements ActionListener { public ColorAction(Color c, JPanel p) { backgroundColor = c; buttonPanel = p; } public void actionPerformed(ActionEvent event) { buttonPanel.setBackground(backgroundColor); private Color backgroundColor; private JPanel buttonPanel;

79 The program ..

80 Mouse Listener Example
public class MouseMove extends JFrame { private Rectangle box; private int x,y; public static void main(String[] args) { MouseMove m = new MouseMove(); } public MouseMove() { super("Mouse Demonstration"); Container cp=getContentPane(); JPanel mousePanel = new MousePanel(); mousePanel.setPreferredSize(new Dimension(300, 300)); cp.add(mousePanel); pack(); setVisible(true);

81 class MousePanel extends JPanel {
int x,y; public MousePanel() { addMouseListener( new MouseAdapter() { public void mousePressed(MouseEvent event) { x=event.getX(); y=event.getY(); System.out.println(event); repaint(); } } ); public void paintComponent(Graphics g) { super.paintComponent(g); g.drawString("You clicked here", x, y);

82 Design Tips GUI code can get very messy Think Design first...
Do not put everything in one class (as many Visual IDE’s do) Quick & dirty = impossible to change! Employ design patterns, e.g. MVC Think Design first... Visual IDE’s can save you a lot of time if used after doing design! Make sure to change default names to meaningful ones!

83 MVC - Design Pattern 14:30 notify read visual update content update
View View View Multiple Views 14:30 Half past two notify model hours: 14 mins: 30 secs: 25 read On Bits ‘n Pieces page... See various implementations of MVC in Java using single reference, observer/observable, propertyChange framework, etc. See clock example Also consider: Traffic light as example visual update content update 1 sec. timer Reset controller receives user interface events

84 MVC . . . Model : The core of the application. This maintains the state and data that the application represents. When significant changes occur in the model, it updates all of its views Controller : The user interface presented to the user to manipulate the application. View : The user interface which displays information about the model to the user. Any object that needs information about the model needs to be a registered view with the model.

85 Observer/Observable Java contains a framework to implement a system where a model is observed by a set of observers. The Observable class represents an observable object, or "data" in the model-view paradigm. It can be subclassed to represent an object that the application wants to have observed. An observable object can have one or more observers. An observer may be any object that implements interface Observer. After an observable instance changes, an application calling the Observable's notifyObservers method causes all of its observers to be notified of the change by a call to their update method.

86 Observable class  void addObserver(Observer o)           Adds an observer to the set of observers for this object, provided that it is not the same as some observer already in the set. protected  void setChanged()           Marks this Observable object as having been changed; the hasChanged method will now return true. void notifyObservers()           If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed.

87 interface Observer public void update(Observable o, Object arg)
This method is called whenever the observed object is changed. An application calls an Observable object's notifyObservers method to have all the object's observers notified of the change. Parameters: o - the observable object. arg - an argument passed to the notifyObservers method.

88 Clock Example, Time Model
public class Time3 extends Observable { private int hour, minute, second; //setters, getters, constructors omitted public void tick() { second = ( second + 1 ) % 60; if ( second == 0 ) { minute = (minute + 1 ) % 60; if ( minute == 0 ) hour = ( hour + 1 ) % 24; } setChanged(); notifyObservers();

89 Clock View (partial code)
public class ClockView extends JPanel implements Observer { Time3 t; public ClockView( Time3 time) { t = time; t.addObserver( this); } public void update( Observable o, Object arg) { repaint(); public void paintComponent( Graphics g) { super.paintComponent(g); g.drawOval(2, 2, 95, 95); double hoursAngle = 2 * Math.PI * ( t.getHour() - 3 ) / 12; g.drawLine( 50, 50, 50 + (int) (25 * Math.cos( hoursAngle)), 50 + (int) (25 * Math.sin( hoursAngle)) );

90 Digital View public class DigitalView extends JLabel implements Observer { Time3 t; public DigitalView( Time3 t) { this.t = t; t.addObserver( this); } public void update(Observable o, Object arg) { setText( t.toUniversalString()); repaint();

91 Clock Panel (partial) public class Clock extends JPanel {
public Clock() { theTime = new Time3(); clockView1 = new ClockView( theTime); clockView2 = new DigitalView( theTime); add( clockView1, CENTER); add( clockView2, SOUTH); timer = new Timer( 1000, new TimerActionListener() ); timer.start(); } Time theTime; Timer timer; ClockView clockView1; DigitalView clockView2; private class TimerActionListener implements ActionListener { public void actionPerformed ( ActionEvent e) { theTime.tick();

92 An Application public class Example1 extends JFrame {
public Example1() { Container c = getContentPane(); c.setLayout( new FlowLayout() ); Clock tc1 = new Clock(); c.add( tc1); Clock tc2 = new Clock(); c.add( tc2); setBounds( 100, 150, 300, 250); setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); setVisible(true); }

93 Output …

94 MVC in Swing ButtonModel model = button.getModel();
                                                                                                                                                                                                                                                 ButtonModel model = button.getModel(); ButtonUI ui = button.getUI();

95 model and ui The model The behavior of the model is captured by the ButtonModel interface. A button model instance encapsulates the internal state of a single button and defines how the button behaves. Its methods can be grouped into four categories -- those that: Query internal state Manipulate internal state Add and remove event listeners Fire events The view and controller The behavior of the view and controller are captured by the ButtonUI interface. Classes that implement this interface are responsible for both creating a button's visual representation and handling user input provided via the keyboard and mouse. Its methods can be grouped into three categories -- those that: Paint Return geometric information Handle AWT events

96 interface ButtonModel
This model is used for check boxes and radio buttons, as well as for normal buttons. For check boxes and radio buttons, pressing the mouse selects the button. For normal buttons, pressing the mouse "arms" the button. Releasing the mouse over the button then initiates a button press, firing its action event. Releasing the mouse elsewhere disarms the button. In use, a UI will invoke setSelected(boolean) when a mouse click occurs over a check box or radio button. It will invoke setArmed(boolean) when the mouse is pressed over a regular button and invoke setPressed(boolean) when the mouse is released. If the mouse travels outside the button in the meantime, setArmed(false) will tell the button not to fire when it sees setPressed. (If the mouse travels back in, the button will be rearmed.) A button is triggered when it is both "armed" and "pressed".

97 Plugging in Custom model
Let’s say we have a button model that just toggles the state, called ToggleButtonModel. We can designate this new type of model to our ordinary JButton like: button.setModel(new toggleButtonModel(button));

98 Changing UI class Given a new UI class FancyButtonUI, we can change the look of our button as: button.setUI(new FancyButtonUI(button));

99 Results

100 MVC Example class Circles extends JFrame implements ActionListener {
public Circles() { radius = new JTextField( 5); radius.addActionListener( this); } // convert given radius to circumference or vice versa public void actionPerformed( ActionEvent e) { DecimalFormat fmt = new DecimalFormat( "0.##"); if ( e.getSource() == radius) { double newRadius = Double.parseDouble( radius.getText() ); double newCircumference = 2 * * newRadius; circumference.setText( fmt.format( newCircumference) ); else { double newCircumference = Double.parseDouble( circumference.getText() ); double newRadius = newCircumference / 2 / 3.142; radius.setText( fmt.format( newRadius) );

101 Separate Circle logic class Circle { double radius, circumference;
public Circle( double r){ setRadius( r); } public void setRadius( double r) { radius = r; circumference = 2 * Math.PI * r; public double getRadius() { return radius; public void setCircumference( double c) { circumference = c; radius = circumference / 2 / 3.142; public double getCircumference() { return circumference;

102 Circle logic separated
class Circles extends JFrame implements ActionListener { Circle aCircle; public Circles( Circle circleObject) { aCircle = circleObject; } // convert given radius to circumference or vice versa public void actionPerformed( ActionEvent e) { if ( e.getSource() == radius) { double newRadius = Double.parseDouble( radius.getText() ); aCircle.setRadius( newRadius); circumference.setText( fmt.format( aCircle.getCircumference() ) ); else …

103 Model aware of view class Circle { double radius, circumference;
Circles panel; public Circle( double r){ setRadius( r); } public void setUI( Circles panel) { this.panel = panel; public void setRadius( double r) { radius = r; circumference = 2 * Math.PI * r; if (panel != null) panel.update(); public double getRadius() { return radius;} public void setCircumference( double c) { …} public double getCircumference() {return circumference;}

104 class Circles extends JFrame implements ActionListener {
Circle aCircle; public Circles( Circle circleObject) { aCircle = circleObject; aCircle.setUI( this); } // convert given radius to circumference or vice versa public void actionPerformed( ActionEvent e) { if ( e.getSource() == radius) { double newRadius = Double.parseDouble( radius.getText() ); aCircle.setRadius( newRadius); else . . . public void update() { DecimalFormat fmt = new DecimalFormat( "0.##"); circumference.setText( fmt.format( aCircle.getCircumference() ) ); radius.setText( fmt.format( aCircle.getRadius() ));

105 Using Observer framework
class Circle extends Observable { double radius, circumference; public Circle( double r){ setRadius( r); } public void setRadius( double r) { radius = r; circumference = 2 * Math.PI * r; setChanged(); notifyObservers(); public double getRadius() {return radius;} public void setCircumference( double c) {… } public double getCircumference() {return circumference;}

106 Using Observable class Circles extends JFrame implements ActionListener, Observer { Circle aCircle; public Circles( Circle circleObject) { aCircle = circleObject; aCircle.addObserver( this); } // convert given radius to circumference or vice versa public void actionPerformed( ActionEvent e) { if ( e.getSource() == radius) { double newRadius = Double.parseDouble( radius.getText() ); aCircle.setRadius( newRadius); else . . . public void update( Observable o, Object arg) { Circle oCircle = (Circle) o; DecimalFormat fmt = new DecimalFormat( "0.##"); circumference.setText( fmt.format( oCircle.getCircumference() ) ); radius.setText( fmt.format( oCircle.getRadius() ));


Download ppt "CS102 – GUI Based on : David Davenport’s slides Spring 2002"

Similar presentations


Ads by Google