GUI ModelViewController CSI 1101 N El Kadri ModelViewController

  • Slides: 33
Download presentation
GUI- Model-View-Controller CSI 1101 N. El Kadri

GUI- Model-View-Controller CSI 1101 N. El Kadri

Model-View-Controller (MVC) pattern • Makes it easier to modify or customize each part; •

Model-View-Controller (MVC) pattern • Makes it easier to modify or customize each part; • Designed to allow for multiple views of the same data; • Binding between the model and the view is done at runtime (rather than compile time), i. e. views can be changed dynamically; • The API of each component is well defined, the model, the controller or the view can be modified/replaced easily; • Allows to focus on each aspect of the application independently.

MVC • Model – the implementation, state: attributes and behaviour; • View – the

MVC • Model – the implementation, state: attributes and behaviour; • View – the outgoing interface, a representation of the model to the outside world; • Controller – the incoming interface, forwards the requests to update the model.

Model • Contains the data of the program and the methods to transform the

Model • Contains the data of the program and the methods to transform the data; • Has no knowledge of either the views or the controllers (sometimes not even a reference); • The View can greatly differ from the Model.

View(s) • A view is an object that presents a visual display of the

View(s) • A view is an object that presents a visual display of the data for the user.

Controller • A controller is an object that provides the means for the user

Controller • A controller is an object that provides the means for the user to change the model or its visual representation. • Knows what can be done to the model, for example, adding or removing an entry.

Example 1 • As our first example, let’s design a graphical user interface for

Example 1 • As our first example, let’s design a graphical user interface for the class Counter.

public class Counter { private int value; public Counter() { value = 0; }

public class Counter { private int value; public Counter() { value = 0; } public void increment() { value++; } public int get. Value() { return value; } public String to. String() { return Integer. to. String( value ); } }

 • To allow for the independent development of the UI, to facilitate the

• To allow for the independent development of the UI, to facilitate the maintenance of the application and to allow for replacement views, let us create an interface to characterize the interactions between the model an its views, Counter. View. public interface Counter. View { public void update(); } • The only knowledge the model has about its view is that a view has a method called update.

Changes to Counter • A new instance variable to reference its view: private Counter.

Changes to Counter • A new instance variable to reference its view: private Counter. View view; • An instance method to set its view: public void set. View(Counter. View v) { view = v; }

Changes to Counter (contd) • increment is changed so that whenever the state of

Changes to Counter (contd) • increment is changed so that whenever the state of the Counter changes the view is notified: public void increment() { value++; view. update(); }

public class Counter { private int value; private Counter. View view; public Counter() {

public class Counter { private int value; private Counter. View view; public Counter() { value = 0; } public void increment() { value++; view. update(); } public int get. Value() { return value; } public void set. View( Counter. View v ) { view = v; } public String to. String() { return Integer. to. String( value ); } }

Controller public class Controller implements Action. Listener { private Counter model; public Controller( Counter

Controller public class Controller implements Action. Listener { private Counter model; public Controller( Counter m ) { model = m; } public void action. Performed( Action. Event e ) { model. increment(); } }

View public class View extends Frame implements Counter. View { private Controller controller; private

View public class View extends Frame implements Counter. View { private Controller controller; private Counter model; private Label value; private Button update = new Button( "Update" ); public View( Counter model ) { super( "Counter UI" ); this. model = model; controller = new Controller( model ); set. Layout( new Grid. Layout( 2, 1 ) ); value = new Label( model. to. String() ); add( value ); add( update ); update. add. Action. Listener( controller ); add. Window. Listener( new Window. Closing. Handler() ); pack(); show(); }

View - cont’d public void update() { value. set. Text( model. to. String() );

View - cont’d public void update() { value. set. Text( model. to. String() ); } private class Window. Closing. Handler extends Window. Adapter { public void window. Closing( Window. Event e ) { System. exit (0); } } // end of View

 • The main program consists of: public class Run { public static void

• The main program consists of: public class Run { public static void main( String[] args ) { Counter model = new Counter(); View view = new View( model ); model. set. View( view ); } }

Another example • Let’s consider a more complex, example that makes use of a

Another example • Let’s consider a more complex, example that makes use of a dialog to enter new data. • This example uses a simplementation of a Stop. Watch based on a fixed size array — since the array has a fixed size, its method add. Time returns false when the array is full. • Stop. Watch is the Model! • For this particular implementation, the model has no knowledge of the user interface at all (no reference to it). • The controller and view are implemented by Stop-Watch. UI (sometimes the Controller and the View are implemented by the same object).

public class Stop. Watch { public static final int CAPACITY = 15; private Time[]

public class Stop. Watch { public static final int CAPACITY = 15; private Time[] times = new Time[ CAPACITY ]; private int last = 0; public boolean add. Time( Time t ) { boolean success; if ( last == times. length ) success = false; else { times[ last ] = t; last++; success = true; } return success; } public Time time. At( int pos ) { return times[ pos ]; } public int size() { return last; } }

public class Stop. Watch. Application { public static void main( String args[] ) {

public class Stop. Watch. Application { public static void main( String args[] ) { Stop. Watch model = new Stop. Watch(); Stop. Watch. UI ui = new Stop. Watch. UI( model ); } }

import java. awt. *; import java. awt. event. *; public class Stop. Watch. UI

import java. awt. *; import java. awt. event. *; public class Stop. Watch. UI extends Frame { // model protected Stop. Watch model; // view private Button b. Time = new Button( "Add New Time" ); private Button b. Quit = new Button( "Quit" ); private List output = new List( 10 ); private Dialog d. Time = new Time. Dialog( this ); //. . .

// Constructor public Stop. Watch. UI( Stop. Watch model ) { super( "Stop. Watch

// Constructor public Stop. Watch. UI( Stop. Watch model ) { super( "Stop. Watch UI" ); this. model = model; add. Window. Listener( new Window. Adapter() { public void window. Closing( Window. Event e ) { System. exit(0); } }); b. Time. add. Action. Listener( new Action. Listener() { public void action. Performed( Action. Event e ) { d. Time. set. Visible( true ); } }); b. Quit. add. Action. Listener( new Action. Listener() { public void action. Performed ( Action. Event e ) { System. exit( 0 ); } });

set. Layout( new Border. Layout() ); add( output, "Center" ); Panel bottom = new

set. Layout( new Border. Layout() ); add( output, "Center" ); Panel bottom = new Panel(); bottom. set. Layout( new Grid. Layout( 1, 2 ) ); bottom. add( b. Time ); bottom. add( b. Quit ); add( bottom, "South" ); pack(); show(); } //. . .

public void display. Times() { output. remove. All(); for ( int i=0; i<model. size();

public void display. Times() { output. remove. All(); for ( int i=0; i<model. size(); i++ ) { output. add( model. time. At( i ). to. String() ); output. make. Visible( i ); } } public void add. Time( Time t ) { if ( ! model. add. Time( t ) ) new Error. Dialog( this, "Maximum Capacity Exceeded" ); else display. Times(); } }

import java. awt. *; import java. awt. event. *; class Time. Dialog extends Dialog

import java. awt. *; import java. awt. event. *; class Time. Dialog extends Dialog { private Stop. Watch. UI parent; private Int. Field in. Hours = new Int. Field(); private Int. Field in. Minutes = new Int. Field(); private Int. Field in. Seconds = new Int. Field(); private Button b. Create = new Button("Create"); private Button b. Cancel = new Button("Cancel"); //. . .

// Constructor Time. Dialog( Stop. Watch. UI parent ) { super( parent, "Time Dialog"

// Constructor Time. Dialog( Stop. Watch. UI parent ) { super( parent, "Time Dialog" , true ); this. parent = parent; b. Create. add. Action. Listener( new Action. Listener() { public void action. Performed( Action. Event e ) { add. Time(); } }); b. Cancel. add. Action. Listener( new Action. Listener() { public void action. Performed( Action. Event e ) { cancel(); } });

set. Layout( new Grid. Layout( 4, 2 ) ); add( new Label( "Hours: "

set. Layout( new Grid. Layout( 4, 2 ) ); add( new Label( "Hours: " ) ); add( in. Hours ); add( new Label( "Minutes: " ) ); add( in. Minutes ); add( new Label( "Seconds: " ) ); add( in. Seconds ); add( b. Create ); add( b. Cancel ); pack(); } //. . .

// instance methods private void add. Time() { int h = in. Hours. get.

// instance methods private void add. Time() { int h = in. Hours. get. Value(); int m = in. Minutes. get. Value(); int s = in. Seconds. get. Value(); parent. add. Time( new Time( h, m, s ) ); set. Visible( false ); } private void cancel() { set. Visible( false ); } } class Int. Field extends Text. Field { public int get. Value() { return Integer. parse. Int( get. Text() ); } }

import java. awt. *; import java. awt. event. *; class Error. Dialog extends Dialog

import java. awt. *; import java. awt. event. *; class Error. Dialog extends Dialog { private Button button; Error. Dialog(Frame parent, String message) { super(parent, "Error Dialog" , true); button = new Button( "Ok" ); button. add. Action. Listener( new Action. Listener () { public void action. Performed( Action. Event e ) { dispose(); } }); add( "Center", new Label( message ) ); add( "South", button ); pack(); set. Visible( true ); } }

Observer/Observable • Two-way associations make classes inseparable. • To avoid these interdependencies, classes are

Observer/Observable • Two-way associations make classes inseparable. • To avoid these interdependencies, classes are often structured as Observer and Observable. • The Observer has an extensive knowledge of the Observable, but the Observable only knows that the Observer can be notified. • Observer is an interface that has a method update. • Observable is an abstract class, that has all the necessary methods to set, delete and notify multiple observers.