410 likes | 423 Views
Learn about the Model-View-Controller pattern and how it separates components, such as the model, view, and controller, to handle user input and display data. Explore the observer pattern and its role in the MVC pattern. Develop a graphical user interface using the MVC architecture.
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