MvcToolkit

Video created from my 401 ((http://www.cs.unc.edu/~dewan/comp401/current/) Fall 13 lecture. See https://mix.office.com/watch/1sxuu7lxtcmye for a downloadable slide-based structured "video", http://www.cs.unc.edu/~dewan/comp401/current/Lectures/MVCToolkit.pptx for the original PPT and http://www.cs.unc.edu/~dewan/comp401/current/Lectures/MVCToolkit.pdf for the pdf.

1.0x

MvcToolkit

Created 3 years ago

Duration 0:56:10
lesson view count 35
Video created from my 401 ((http://www.cs.unc.edu/~dewan/comp401/current/) Fall 13 lecture. See https://mix.office.com/watch/1sxuu7lxtcmye for a downloadable slide-based structured "video", http://www.cs.unc.edu/~dewan/comp401/current/Lectures/MVCToolkit.pptx for the original PPT and http://www.cs.unc.edu/~dewan/comp401/current/Lectures/MVCToolkit.pdf for the pdf.
Select the file type you wish to download
Slide Content
  1. Comp 401MVC and User-Interface Toolkits

    Slide 1 - Comp 401MVC and User-Interface Toolkits

    • Instructor: Prasun Dewan
  2. Prerequisites

    Slide 2 - Prerequisites

    • MVC
  3. Counter Application

    Slide 3 - Counter Application

  4. getValue()

    Slide 4 - getValue()

    • Complete MVC
    • Model
    • View
    • add()
    • Controller
    • Performs Input
    • Performs Output
    • Notification Method
    • Model Connection Method
    • Observer Registration Method
  5. More  Sophisticated AWT/Swing Counter User Interface

    Slide 5 - More Sophisticated AWT/Swing Counter User Interface

  6. Widgets and Display Logical Structure

    Slide 6 - Widgets and Display Logical Structure

    • JFrame
    • JButton
    • JTextField
    • HAS-A
    • HAS-A
    • Layout?
  7. AWT Single Frame Composer

    Slide 7 - AWT Single Frame Composer

    • public class SingleFrameAWTComposer {
    • public static void main (String args[]) {
    • // compose AWT components
    • JFrame frame = new JFrame("AWT Controller and View");
    • JButton button = new JButton("Increment");
    • JTextField textField = new JTextField();
    • frame.setLayout(new GridLayout(2,1));
    • frame.add(textField);
    • frame.add(button);
    • frame.setSize(200, 200);
    • frame.setVisible(true);
    • //compose model view and controller
    • ObservableCounter model = new AnObservableCounter();
    • }
    • }
    • Separate layout object
  8. Widgets and Display Logical Structure

    Slide 8 - Widgets and Display Logical Structure

    • JFrame
    • JButton
    • JTextField
    • HAS-A
    • HAS-A
    • HAS-A == is parent of in logical structure
    • Has a reference to
    • How should the button tell a controller that it has been pressed so it can increment the counter?
    • How should the view tell the text field to display a new String.
    • Output vs. Input widgets?
  9. Read Methods

    Slide 9 - Read Methods

    • Write Methods
    • MVC and Toolkits
    • Model
    • View
    • Controller
    • Performs Input
    • Performs Output
    • Notification Method
    • Observer Registration Method
    • Notification Method
    • Observable Widget (Button, TextField)
    • Observer Registration Method
    • Controller and view can be tightly coupled
    • Write Methods
  10. getValue()

    Slide 10 - getValue()

    • increment()
    • MVC in Example Application
    • ObservableCounter
    • ACounter JTextFieldView
    • ACounterJButton Controller
    • update()
    • actionPerformed()
    • JButton
    • setText()
    • JTextField
    • addActionListener()
    • Press
  11. getValue()

    Slide 11 - getValue()

    • increment()
    • MVC in Example Application (Review)
    • ObservableCounter
    • ACounter JTextFieldView
    • ACounterJButton Controller
    • update()
    • actionPerformed()
    • JButton
    • setText()
    • JTextField
    • addActionListener()
    • Press
  12. Observer Pattern in Java Toolkit

    Slide 12 - Observer Pattern in Java Toolkit

    • import java.awt.ActionEvent;
    • public interface ActionListener {
    • public void actionPerformed(ActionEvent e);
    • }
    • When you edit text and hit return this event sent by JTextField, TextField widget to its listeners such as ObjectEditor
    • When you press a button, this event sent by Button/Jbutton to its listeners such as ObjectEditor
    • import java.awt.ActionListener;
    • public void addActionListener (ActionListener actionListener)
  13. Counter Observable

    Slide 13 - Counter Observable

    • public class AnObservableCounter implements ObservableCounter {
    • int counter = 0;
    • ObserverList observers = new AnObserverList();
    • public void add (int amount) {
    • counter += amount;
    • notifyAllObservers();
    • }
    • public int getValue() {
    • return counter;
    • }
    • public void addObserver(CounterObserver observer) {
    • observers.addElement(observer);
    • observer.update(this);
    • }
    • public void removeObserver(CounterObserver observer) {
    • observers.removeElement(observer);
    • }
    • void notifyAllObservers() {
    • for (int observerNum = 0; observerNum < observers.size();
    • observerNum++)
    • observers.elementAt(observerNum).update(this);
    • }
    • }
  14. Button Controller also an Observer

    Slide 14 - Button Controller also an Observer

    • public class ACounterJButtonController implements CounterController, ActionListener {
    • JButton button;
    • ObservableCounter counter;
    • public ACounterJButtonController(JButton theButton) {
    • button = theButton;
    • button.addActionListener(this);
    • }
    • public void setModel (ObservableCounter theCounter) {
    • counter = theCounter;
    • }
    • // do not need to implement anything in this controller
    • public void processInput() {
    • }
    • //ActionListener method
    • public void actionPerformed(ActionEvent arg0) {
    • counter.add(1);
    • }
    • }
  15. TextField View Invoking Widget Write Methods

    Slide 15 - TextField View Invoking Widget Write Methods

    • public class ACounterJTextFieldView implements CounterObserver {
    • JTextField textField;
    • public ACounterJTextFieldView(JTextField theTextField){
    • textField = theTextField;
    • }
    • public void update(ObservableCounter counter) {
    • textField.setText("" + counter.getValue());
    • }
    • }
  16. Dual Role Composer

    Slide 16 - Dual Role Composer

    • public class SingleFrameAWTComposer {
    • public static void main (String args[]) {
    • // compose AWT components
    • JFrame frame = new JFrame("AWT Controller and View");
    • JButton button = new JButton("Increment");
    • JTextField textField = new JTextField();
    • frame.setLayout(new GridLayout(2,1));
    • frame.add(textField);
    • frame.add(button);
    • frame.setSize(200, 200);
    • frame.setVisible(true);
    • //compose model view and controller
    • ObservableCounter model = new AnObservableCounter();
    • CounterObserver view =
    • new ACounterJTextFieldView(textField);
    • model.addObserver(view);
    • CounterController controller =
    • new ACounterJButtonController(button);
    • controller.setModel(model);
    • }
    • }
  17. Window Systems and UI  Toolkits

    Slide 17 - Window Systems and UI Toolkits

    • Window system
    • Provides hierarchical rectangular areas called windows
    • Windows have no associated behavior
    • User Interface toolkit
    • Provides widgets: windows with some behavior
    • E.g: JTextField, Jslider, JMenuItem, JMenu
    • Widgets are observables and the ones we have seen
    • Support action listeners through the addActionListener method
    • Notify listeners about ActionEvent
    • Widgets provide writemethods to change their state
    • setText(), setValue()
    • Window Toolkit
    • Window system + user interface toolkit
  18. MVC with Toolkit Widgets for I/O

    Slide 18 - MVC with Toolkit Widgets for I/O

    • Like regular MVC:
    • Controller for input, View for output, and Model for semantics
    • Main program instantiates model, views and controllers and connects these objects together
    • Additional twists;
    • The main program also builds a widget/window tree
    • A controller
    • gets in its constructor (or through a setter method) a set of input widgets such JTextField, JMenuItem and registers itself as a listener of these widgets
    • On receiving event from input widgets, calls write methods in the model
    • A view
    • gets in its constructor a set of output widgets such as JTextField
    • calls write methods in them when it receives notifications from the model
  19. Controller/View Roles with widgets

    Slide 19 - Controller/View Roles with widgets

    • Controller:
    • Receives events from widgets and calls read methods in the widgets
    • Calls write methods in the model
    • Essentially reads widget state and writes model state: widget state  model state)
    • View
    • Receives notifications in the model
    • Calls read methods in the model
    • Calls write methods in the widgets
    • Essentially reads model state and writes widget state: model state  widget state
  20. Writing Only the Observable

    Slide 20 - Writing Only the Observable

    • Read Methods
    • Write Methods
    • Performs Input
    • Performs Output
    • propertyChange (PropertyChangeEvent )
    • addPropertyChangeListener (PropertyChangeListener )
    • Model
    • OE View
    • OE Controller
  21. The Full App

    Slide 21 - The Full App

    • Read Methods
    • Write Methods
    • Performs Input
    • Performs Output
    • propertyChange (PropertyChangeEvent )
    • addPropertyChangeListener (PropertyChangeListener )
    • Model
    • Custom View
    • Custom Controller
  22. AWT Single Frame Composer

    Slide 22 - AWT Single Frame Composer

    • public class SingleFrameAWTComposer {
    • public static void main (String args[]) {
    • // compose AWT components
    • JFrame frame = new JFrame("AWT Controller and View");
    • JButton button = new JButton("Increment");
    • JTextField textField = new JTextField();
    • frame.setLayout(new GridLayout(2,1));
    • frame.add(textField);
    • frame.add(button);
    • frame.setSize(200, 200);
    • frame.setVisible(true);
    • //compose model view and controller
    • ObservableCounter model = new AnObservableCounter();
    • CounterObserver view =
    • new ACounterJTextFieldView(textField);
    • model.addObserver(view);
    • CounterController controller =
    • new ACounterJButtonController(button);
    • controller.setModel(model);
    • }
    • }
    • Separate button and text field into different frames?
  23. Widgets and Display Logical Structure

    Slide 23 - Widgets and Display Logical Structure

    • JFrame
    • JButton
    • JTextField
    • JFrame
  24. AWT Multi Frame Composer

    Slide 24 - AWT Multi Frame Composer

    • public class MultiFrameButtonTextFieldAWTComposer {
    • public static void main (String args[]) {
    • ObservableCounter model = new AnObservableCounter();
    • CounterController controller = createControllerAndControllerFrame();
    • CounterObserver view = createViewAndViewFrame();
    • model.addObserver(view);
    • controller.setModel(model);
    • }
    • public static CounterController createControllerAndControllerFrame() {
    • JFrame frame = new JFrame("Counter Controller");
    • JButton button = new JButton("Increment");
    • frame.add(button);
    • frame.setSize(200, 100);
    • frame.setVisible(true);
    • return new ACounterJButtonController(button);
    • }
    • public static CounterObserver createViewAndViewFrame() {
    • JFrame frame = new JFrame("Counter View");
    • JTextField textField = new JTextField();
    • frame.add(textField);
    • frame.setSize(200, 100);
    • frame.setVisible(true);
    • return new ACounterJTextFieldView(textField);
    • }
    • }
    • If two pieces can change independently, separate them
    • Separation of controller and view allows reuse by writing a different composer
  25. Reusing View with Different Input Widget

    Slide 25 - Reusing View with Different Input Widget

  26. Widgets and Display Logical Structure

    Slide 26 - Widgets and Display Logical Structure

    • JFrame
    • JMenuBar
    • JTextField
    • JMenu
    • JMenu
  27. getValue()

    Slide 27 - getValue()

    • increment()
    • Original Controller and Input Widget
    • ObservableCounter
    • ACounter JTextFieldView
    • ACounterJButton Controller
    • update()
    • actionPerformed()
    • JButton
    • setText()
    • JTextField
    • addActionListener()
  28. getValue()

    Slide 28 - getValue()

    • increment()
    • New Controller and Input Widget
    • ObservableCounter
    • ACounter JTextFieldView
    • ACounterJMenu ItemController
    • update()
    • actionPerformed()
    • JMenuItem
    • setText()
    • JTextField
    • addActionListener()
    • addActionListener() not implemented by a common super type
    • Must create a new controller
  29. Exists vs. Ideal

    Slide 29 - Exists vs. Ideal

    • JButton
    • JMenuItem
    • JTextField
    • ActionNotifier
    • addActionListener()
    • IS-A
    • JButton
    • JMenuItem
    • JTextField
    • addAction
    • Listener()
    • addAction
    • Listener()
    • addAction
    • Listener()
    • Swing/AWT
    • Swing/AWT++
  30. getValue()

    Slide 30 - getValue()

    • increment()
    • Using JTextField
    • ObservableCounter
    • ACounter JTextFieldView
    • ACounterJMenu Controller
    • update()
    • actionPerformed()
    • JButton
    • setText()
    • JTextField
    • addActionListener()
  31. getValue()

    Slide 31 - getValue()

    • increment()
    • Using TextField
    • ObservableCounter
    • ACounter TextFieldView
    • ACounterJMenu Controller
    • update()
    • actionPerformed()
    • JButton
    • setText()
    • TextField
    • addActionListener()
    • Must create a new view
  32. Exists vs. Ideal

    Slide 32 - Exists vs. Ideal

    • TextField
    • JTextField
    • TextWidget
    • IS-A
    • JTextField
    • setText()
    • Swing/AWT
    • Swing/AWT++
    • getText()
    • TextField
    • setText()
    • getText()
    • setText()
    • getText()
  33. Menu Item Controller

    Slide 33 - Menu Item Controller

    • public class ACounterJMenuItemController
    • implements CounterController, ActionListener {
    • JMenuItem menuItem;
    • ObservableCounter counter;
    • public ACounterJMenuItemController(JMenuItem theMenuItem) {
    • menuItem = theMenuItem;
    • menuItem.addActionListener(this);
    • }
    • public void setModel (ObservableCounter theCounter) {
    • counter = theCounter;
    • }
    • public void processInput() {
    • }
    • public void actionPerformed(ActionEvent arg0) {
    • counter.add(1);
    • }
    • }
  34. Menu Item Composer

    Slide 34 - Menu Item Composer

    • public class SingleFrameAWTMenuItemTextFieldComposer {
    • public static void main (String args[]) {
    • // compose AWT components
    • JFrame frame = new JFrame("AWT Controller and View");
    • JMenuItem menuItem = new JMenuItem("Increment");
    • JMenu menu = new JMenu("Counter");
    • JMenuBar menuBar = new JMenuBar();
    • JTextField textField = new JTextField();
    • frame.add(textField);
    • menu.add(menuItem);
    • menuBar.add(menu);
    • frame.setJMenuBar(menuBar);
    • frame.setSize(250, 125);
    • frame.setVisible(true);
    • //compose model view and controller
    • ObservableCounter model = new AnObservableCounter();
    • CounterObserver view = new ACounterJTextFieldView(textField);
    • model.addObserver(view);
    • CounterController controller = new ACounterJMenuItemController(menuItem);
    • controller.setModel(model);
    • }
    • }
  35. MVC, Toolkits and Beans

    Slide 35 - MVC, Toolkits and Beans

    • import java.beans.PropertyChangeEvent;
    • import java.beans.PropertyChangeListener;
    • import util.annotations.ObserverRegisterer;
    • import util.annotations.ObserverTypes;
    • import util.models.PropertyListenerRegisterer;
    • public class AnObservableBMISpreadsheet
    • implements BMISpreadsheet, PropertyListenerRegisterer {
    • PropertyListenerSupport propertyListenerSupport =
    • new APropertyListenerSupport();
    • @ObserverRegisterer(ObserverTypes.PROPERTY_LISTENER)
    • public void addPropertyChangeListener(
    • PropertyChangeListener listener) {
    • propertyListenerSupport.addElement(listener);
    • }
    • public void setWeight(double newWeight) {
    • double oldWeight = weight;
    • double oldBMI = getBMI();
    • weight = newWeight;
    • propertyListenerSupport.notifyAllListeners(
    • new PropertyChangeEvent(this, "weight", oldWeight, newWeight));
    • propertyListenerSupport.notifyAllListeners(
    • new PropertyChangeEvent(this, "bmi", oldBMI, getBMI()));
    • }
    • }
    • BMI value shown in two different widgets
  36. Widgets and Model Structures

    Slide 36 - Widgets and Model Structures

    • JFrame
    • JTextField
    • JTextField
    • JProgressBar
    • JSlider
    • BMISpreadsheet
    • double
    • double
    • double
    • HAS-A
    • height
    • weight
    • bmi
    • JLabel
    • JLabel
    • JPanel
    • JPanel
    • JPanel
    • Causes change in
    • Causes change in
    • Causes change in
  37. Read Methods

    Slide 37 - Read Methods

    • Write Methods
    • MVC and Toolkits: General Structure
    • Model
    • View
    • Controller
    • Notification Method
    • Notification Method
    • Observable Widget (Button, TextField)
    • Observer Registration Method
    • Write Methods
  38. setHeight()

    Slide 38 - setHeight()

    • MVC and Toolkits: BMI SPreadsheet
    • BMISpreadsheet
    • ABMISpreadsheetController
    • actionPerformed()
    • setText()
    • setWeight()
    • JTextField
    • JTextField
    • ABMISpreadsheet View
    • addAction Listener ()
    • addAction Listener ()
    • JSlider
    • JProgress Bar
    • property Changed()
    • setValue()
    • setText()
    • setValue()
    • enter
    • enter
  39. setHeight()

    Slide 39 - setHeight()

    • MVC and Toolkits: General Structure
    • BMISpreadsheet
    • ABMISpreadsheetController
    • actionPerformed()
    • setText()
    • setWeight()
    • JTextField
    • JTextField
    • Same method called by two widgets
    • Performs different actions
    • ActionEvent
    • getSource()
    • Better to subdivide controller into height and weight controllers
    • Illustrates the use of getSource()
  40. BMI Controller

    Slide 40 - BMI Controller

    • public class ABMISpreadsheetController implements ActionListener {
    • JTextField height, weight;
    • BMISpreadsheet bmiSpreadsheet;
    • public ABMISpreadsheetController (
    • BMISpreadsheet theBMISpreadsheet,
    • JTextField theHeight, JTextField theWeight) {
    • height = theHeight;
    • weight = theWeight;
    • bmiSpreadsheet = theBMISpreadsheet;
    • height.addActionListener(this);
    • weight.addActionListener(this);
    • }
    • public void actionPerformed(ActionEvent event) {
    • JTextField source = (JTextField) event.getSource();
    • String text = source.getText();
    • double val = Double.parseDouble(text);
    • if (source == height) {
    • bmiSpreadsheet.setHeight(val);
    • } else {
    • bmiSpreadsheet.setWeight(val);
    • }
    • }
    • }
  41. BMI View

    Slide 41 - BMI View

    • public class ABMISpreadsheetView implements PropertyChangeListener{
    • JTextField heightField, weightField;
    • JSlider bmiSlider;
    • JProgressBar bmiProgressBar;
    • public ABMISpreadsheetView (JTextField theHeightField,
    • JTextField theWeightField, JSlider theBMISlider,
    • JProgressBar theBMIProgressBar) {
    • heightField = theHeightField;
    • weightField = theWeightField;
    • bmiSlider = theBMISlider;
    • bmiProgressBar = theBMIProgressBar;
    • }
    • public void propertyChange(PropertyChangeEvent event) {
    • String propertyName = event.getPropertyName();
    • Double newValue = (Double) event.getNewValue();
    • if (propertyName.equalsIgnoreCase("height")) {
    • heightField.setText(newValue.toString());
    • } else if (propertyName.equalsIgnoreCase("weight")) {
    • weightField.setText(event.getNewValue().toString());
    • } else if (propertyName.equalsIgnoreCase("bmi")) {
    • double newBMI = newValue;
    • bmiSlider.setValue((int) newBMI);
    • bmiProgressBar.setValue((int) newBMI);
    • }}}}
  42. BMI Composer

    Slide 42 - BMI Composer

    • public class BMIFrameComposer {
    • static JFrame frame = new JFrame("BMI Spreadsheet");
    • static JTextField heightField = new JTextField();
    • static JLabel heightLabel = new JLabel("Height:");
    • static JPanel heightPanel = new JPanel();
    • static JTextField weightField = new JTextField();
    • static JLabel weightLabel = new JLabel("Weight:");
    • static JPanel weightPanel = new JPanel();
    • static JSlider bmiSlider = new JSlider();
    • static JProgressBar bmiProgressBar = new JProgressBar();
    • static JPanel bmiPanel = new JPanel();
    • public static void main (String args[]) {
    • composeLabelledField(heightPanel, heightLabel, heightField);
    • composeLabelledField(weightPanel, weightLabel, weightField);
    • composeBMI();
    • composeFrame();
    • composeMVC();
    • }
  43. BMI Composer (contd)

    Slide 43 - BMI Composer (contd)

    • public static void composeBMI() {
    • bmiPanel.setLayout(new GridLayout(1, 2));
    • bmiPanel.add(bmiSlider);
    • bmiPanel.add(bmiProgressBar);
    • }
    • public static void composeFrame() {
    • frame.setLayout(new GridLayout(3, 1));
    • frame.add(heightPanel);
    • frame.add(weightPanel);
    • frame.add(bmiPanel);
    • frame.setSize(250, 150);
    • frame.setVisible(true);
    • }
    • public static void composeMVC() {
    • BMISpreadsheet bmiSpreadsheet =
    • new AnObservableBMISpreadsheet();
    • new ABMISpreadsheetController(bmiSpreadsheet,
    • heightField, weightField);
    • PropertyChangeListener bmiSpreadsheetView =
    • new ABMISpreadsheetView(heightField, weightField,
    • bmiSlider, bmiProgressBar);
    • bmiSpreadsheet.
    • addPropertyChangeListener(bmiSpreadsheetView);
    • }}
  44. MVC, Toolkits + Beans

    Slide 44 - MVC, Toolkits + Beans

    • Like MVC with toolkits we saw earlier
    • Additional twists
    • Model now is divided into multiple properties
    • User interface composed of multiple input/output widgets
    • View must now implement the Java java.beans.PropertyChangeListener interface
    • Do not implement your interface that follows the same naming conventions
    • View and controllers can get multiple widgets from main, usually one for each properties they change/display, to which they store references. Sometimes a view may display the same property using multiple widgets (e.g. slider and progress bar for bmi) or a controller may listen to multiple widgets for setting a property (e.g. menu item and button)
  45. Widgets and Model Structures

    Slide 45 - Widgets and Model Structures

    • Mapping can be done automatically or manually
    • JFrame
    • JTextField
    • JTextField
    • JProgressBar
    • JSlider
    • BMISpreadsheet
    • double
    • double
    • double
    • HAS-A
    • height
    • weight
    • bmi
    • JLabel
    • JLabel
    • JPanel
    • JPanel
    • JPanel
    • Causes change in
    • Causes change in
    • Causes change in
  46. Visualizing Model Structure

    Slide 46 - Visualizing Model Structure

  47. Visualizing Model Structure

    Slide 47 - Visualizing Model Structure

  48. Model Structure

    Slide 48 - Model Structure

  49. Visualizing Widget Structure

    Slide 49 - Visualizing Widget Structure

  50. Widget Structures

    Slide 50 - Widget Structures