410 likes | 595 Views
Chapter 18 Integrating user interface and model: the Model-View-Controller pattern. Objectives. After studying this chapter you should understand the following: the Model-View-Controller pattern: components and their roles;
E N D
Chapter 18Integrating user interface and model: the Model-View-Controller pattern
Objectives • After studying this chapter you should understand the following: • the Model-View-Controller pattern: components and their roles; • the observer pattern, as realized by the class Observable and interface Observer, and its use in the MVC pattern. • Also, you should be able to: • write a graphical user interface for a simple application using the MVC architecture. NH-Chapter 18
Model-View-Controller • An Application structure • model components –objects that model and solve problem; • view components –objects that display model; • controller components –objects that handle user input. NH-Chapter 18
Model-View-Controller advantages • Processing of input and output is separate; • Controllers can be interchanged, allowing different user interaction modes; • Allows multiple views of model. NH-Chapter 18
View view1 View view3 Controller control1 Model View view2 Controller control2 M-V-C architecture NH-Chapter 18
Observer/Observable relationships • java.util provides class Observable, interface Observer. • Observer is client and Observable is server. • Observer registers with the Observable, • Observable informs Observer when it changes state. NH-Chapter 18
M-V-C example • Model: a right triangle. • base and height can be modified. • Three different views of triangle. • View one displays lengths of sides. • View two displays triangle graphically. • View three logs changes in triangle state to file. • A controller for view one, to modify triangle. • No controller for other views. NH-Chapter 18
RightTriangle class publicclass RightTriangle { privateint base; privateint height; privateint hypotenuse; public RightTriangle (int base, int height) { this.base = base; this.height = height; setHypotenuse(); } publicint base () { returnthis.base; } publicint height () { returnthis.height; } publicint hypotenuse () { returnthis.hypotenuse; } publicvoid setBase (int newBase) { this.base = newBase; setHypotenuse(); } publicvoid setHeight (int newHeight) { this.height = newHeight; setHypotenuse(); } privatevoid setHypotenuse () { this.hypotenuse = (int) Math.round( Math.sqrt(base*base + height*height)); } }//end RightTriangle. NH-Chapter 18
Observable methods • java.util.Observable class specification provides several methods; among those: publicvoid addObserver (Observer o); protected void setChanged (); publicvoid notifyObservers (); publicvoid notifyObservers (Object arg); NH-Chapter 18
Structuring an Observer/Observable • RightTriangle extends Observable: • When RightTriangle changes state, to notify all registered observers of the event, modifies commands to add: publicclass RightTriangle extendsObservable… • All views are Observer’sof RightTriangle instance rt • Client Observer registers to rt invoking addObserver. rt.addObserver(this); setChanged(); notifyObservers(); NH-Chapter 18
Implementing an Observable • RightTriangle changes state in setBase or setHeight : public void setBase (int newBase) { this.base = newBase; setHypotenuse(); setChanged(); notifyObservers(); } public void setHeight (int newHeight) { this.height = newHeight; setHypotenuse(); setChanged(); notifyObservers(); } NH-Chapter 18
Interface Observer interface Observer { void update (Observable o, Object arg); } NH-Chapter 18
class RTObserver implements Observer { private RightTriangle target; // Create an observer of RightTriangle rt. public RTObserver (RightTriangle rt) { target = rt; target.addObserver(this); … } public void update((Observable o, Object arg){ do something about o’s state change. } … } observer registers with model Observer structure • Observer must know target object. • Observer registers itself with the target. • When target notifies observer, observer executes update. NH-Chapter 18
A simple view and controller for RightTriangle • Build a view that shows the three components of the triangle in text fields. • Controller will capture input from text fields labeled Base and Height, and modify state of the RightTriangle appropriately. NH-Chapter 18
The View • View extends JPanel and implements Observer. • RightTriangle to display is provided as constructor argument. • class TextView extends JPanel implements Observer { • privatefinalstaticint FIELD_SIZE = 16; • private JTextField base; • private JTextField height; • private JTextField hypotenuse; • public TextView (RightTriangle model) { • super(); • … • base = new JTextField(FIELD_SIZE); • base.setActionCommand("Base"); • … • height = new JTextField(FIELD_SIZE); • height.setActionCommand("Height"); • … • hypotenuse = new JTextField(FIELD_SIZE); • hypotenuse.setEditable(false); • … • } NH-Chapter 18
The View • View extends JPanel and implements Observer. • RightTriangle to display is provided as constructor argument. NH-Chapter 18
The View • When model changes state, notifies view to update text fields. • View’s update queries model for new state information, and writes it into text fields: publicvoid update (Observable model, Object arg) { int side; RightTriangle rt = (RightTriangle)model; side = rt.base(); base.setText(String.valueOf(side)); side = rt.height(); height.setText(String.valueOf(side)); side = rt.hypotenuse(); hypotenuse.setText(String.valueOf(side)); } NH-Chapter 18
Controller structure • Captures user input from base and height text fields • must have references to the text fields, • must respond to ActionEvents generated by text fields, • must be an ActionListener, • must be added as listener to text fields. • Updates model. • This is response to ActionEvent text fields generate. • Must have reference to RightTriangle. NH-Chapter 18
Controller structure • private class TVController implements ActionListener { • private RightTriangle model; • /** • * Create a new controller for this TextView of the • * specified RightTriangle. • */ • public TVController (RightTriangle model) { • this.model = model; • ¹ TextView.this.base.addActionListener(this); • TextView.this.height.addActionListener(this); • } NH-Chapter 18
Controller structure • /** • * Update the model in response to user input. • */ • publicvoid actionPerformed (ActionEvent e) { • JTextField tf = (JTextField)e.getSource(); • try { • int i = Integer.parseInt(tf.getText()); • if (i < 0) thrownew NumberFormatException(); • String which = e.getActionCommand(); • if (which.equals("Base")) • model.setBase(i); • else • model.setHeight(i); • } catch (NumberFormatException ex) { • TextView.this.update(model, null); • } • } NH-Chapter 18
Model, View and Controller NH-Chapter 18
provides Game Pile s e s u 2 «interface» directs Player AbstractPlayer InteractivePlayer IndependentPlayer Nim Game : Model NH-Chapter 18
Nim Game : TUI NH-Chapter 18
Nim Game : TUI v.s. GUI design • TUI design: • TUIController • registers with InteractivePlayer, • prompts and reads user’s move, forwards it to InteractivePlayer. • The play loop is in the interface. NH-Chapter 18
Nim Game : GUI design NH-Chapter 18
Nim Game : TUI v.s. GUI design • GUI design • No explicit loop coded. • User repeats some event. • NimController • When user presses an input button it invokes setNumberToTake on InteractivePlayer. • Invokes Game’s play, • once for InteractivePlayer, • once for IndependentPlayer. NH-Chapter 18
View • Display composed of four panels: • a panel to display number of sticks remaining, • two panels each with a text field to report player’s moves, • a panel containing buttons for user to make a move. NH-Chapter 18
NimController NH-Chapter 18
View • A NimInterface instance: • builds display, • observes the Game. NH-Chapter 18
Model’s Game • When Game completes a play, it notifies its Observers. public void play () { if (!gameOver()) { nextPlayer.takeTurn(pile,MAX_ON_A_TURN); previousPlayer = nextPlayer; nextPlayer = otherPlayer(nextPlayer); setChanged(); notifyObservers(); } } NH-Chapter 18
GUI structure • User selects “New Game” from main menu. • Menu item listener invokes NimController’s initializeGame: • displays a JDialog to get initialization data from user, • creates a Game. NH-Chapter 18
NimInterface • When notified, • queries Game, • updates display. • NimInterface responsible for • displaying the number of sticks remaining in the game; • reporting the winner when the game is over. NH-Chapter 18
Sub-views • NimInterface • defines an inner class PlayerView with the responsibility to report player’s moves. • A PlayerView observes a Player, and updates the text field when the Player takes a turn. NH-Chapter 18
Delaying IdependentPlayer’s move • NimController invokes Game’s play, • once for InteractivePlayer, • once for IndependentPlayer. • Need a delay between the two play invocations. NH-Chapter 18
Delaying IdependentPlayer’s move public void actionPerformed (ActionEvent e) { … user.setNumberToTake(number); game.play(); nhUtilities.utilities.Control.sleep(2); //delay game.play(); … } • Attempt to delay the two plays fails. • Application will pause, but moves appear to take place at the same time. NH-Chapter 18
Delaying IdependentPlayer’s move Event dispatch thread user presses button button-press event handler starts display updates resulting from InteractivePlayer move are scheduled thread sleeps for two seconds display updates resulting form IndependentPlayer move are scheduled button-press event handler completes display is updated NH-Chapter 18
Scheduling a move to delay the action • NimController uses javax.swing.Timer to schedule IndependentPlayer’s play seconds after play of InteractivePlayer. • User’s Button-press event handling is complete. • IndependentPlayer’s move occurs after and when scheduled. NH-Chapter 18
MVC and Swing components • Swing components are structured using MVC pattern. • Each Swing JComponent has an associated model object responsible for maintaining component’s state. • JButton or JCheckBox has a ButtonModel, • JTextArea or JTextField has a Document. • A Swing component delegates view and control responsibilities to its UI delegate. • The package javax.swing.plaf contains an abstract delegate class for each Swing component. NH-Chapter 18
Summary • Overview basic format of Model-View-Controller pattern. • MVC commonly used to structure event-driven graphical user interfaces. • With MVC, interface responsibilities are partitioned into two segments: • view has display responsibilities, • controller modifies model in accordance with user input. NH-Chapter 18
Summary • Developed three views of a right triangle. • Noted Java Observer interface and Observable class for implementing the observes relationship. • Fundamental relationship between view and model is observes, implemented by • making model object an extension of the class Observable, • view implements interface Observer. • Added a graphical user interface to the nim game, using the MVC pattern. NH-Chapter 18
Summary • Swing components are structured along the lines of MVC. • Each Swing component has • an associated model object responsible for maintaining component’s state. • a UI delegate, to which view and control responsibilities are delegated. • This structure allows to change application look-and-feel in a system-independent way. NH-Chapter 18