SlideShare una empresa de Scribd logo
1 de 15
Descargar para leer sin conexión
Java Swing Custom GUI MVC Component
                     Tutorial
         Prakash Manandhar, Sagun Dhakhwa, Ishwor Thapa
 Sambad Project (www.sambad.org), Madan Puraskar Pustakalaya, Nepal
                                  July 13, 2006


1 Introduction
The Model-View-Controller (MVC) architecture is one of the first widely acclaimed
architectures for GUI systems (Gamma et al., 1995;Buschmann et al., 1996). Contem-
porary GUI APIs (and even some Web APIs) - like Java Swing, Microsoft Foundation
Classes and even its newest incarnation WinFX - are also based on modifications of the
MVC architectural pattern (Eckstein et al., 1998; Kruglinski, 1995; Livermore et al.,
2006). The MVC does have its fair share of critics, for example Holub [1999] goes so
far as to say that MVC is not object-oriented, but we think it is a logical and proven
system for beginning GUI system designers and programmers.
    In this tutorial we take you through creating several simple custom components
from scratch using Java Swing as the implementation platform. It is hoped that readers
will get a better understanding of the MVC architecture from this document as well as
find within it a cook-book for creating MVC style custom GUI components for Java
Swing.
    We implement a simple GUI with toggle switches and LED displays that controls
output to the console.


                      Figure 1: Screenshot of finished program




                                          1
Figure 2: Model View Controller Architecture
                                        views




                                      on = true


                                       model


2 Model View Controller
The Model View Controller Architecture (MVC) is software design architectural pat-
tern which breaks an application or just an application’s interface into three types of
objects namely, Model, View and Controller (Gamma et al., 1995). Model is the ap-
plication object, View is the screen presentation and Control determines how UI reacts
to the user input. MVC separates these three components, which used to be coupled
together in architectures prior to MVC, yielding more flexibility and reusability. The
model encapsulates more than just data and function that operates on it. It represents
not just the state of the UI but also how the UI works, making it easier to use real-
world modeling (e.g,: Switch and Bulb) techniques in defining the models (Helman,
1998).The model contains the actual state of the UI component. When the state of the
UI component changes, the model data should reflect the change. The model then no-
tifies all the views which subscribe it, in response the views update themselves. View
is responsible for displaying the state of the model on a device. It attaches to a model
and render its contents on the device. The controller subscribes both the model and the
viewport and knows the type of both in order to translate user input into application
response.The views in a MVC can be nested, i.e. they can contain server sub-views.
     The MVC allows to change the response of the view to the user input without
changing the view presentation. A view uses the controller to implement a particual
response strategy of the response.




3 Writing the Model
Toggle Model represents the state of the component. The model has either the ’ON’
state or ’OFF’ state. It also coordinates with the view by notifying when this model
changes the state.



                                           2
To represent the state of the model, we simply define a boolean variable called on,
which when ’true’ marks the ’ON’ state of the model and ’false’ marks the ’OFF’ state
of the model.
    To maintain link between model and view, model should notify its views with a
message that the state has been changed. Here in this example when the state is
changed, the Toggle model notifies all its event listeners. Listeners are registered to
this model by addToggleListener() call.
package np.org.mpp.sambad.tutorial.mvc;

import java.util.ArrayList;
import java.util.List;

/**
 * A simple model that keeps track whether something is On or Off.
 * @author Prakash Manandhar
 */
public class ToggleModel {

         // model state
         private boolean on;

         // list of listeners to this model
         private List<ToggleListener> listeners = new ArrayList<ToggleListener>();

         /**
           * Default constructors. Initially the model is <em>not on</em>.
           */
         public ToggleModel ()
         {
                  on = false;
         }

         /**
           * Constructor with given intial state.
           * @param isOn
           */
         public ToggleModel (boolean isOn)
         {
                  on = isOn;
         }

         /**
           * @return is this toggle on?
           */
         public boolean isOn ()
         {
                  return on;
         }

         /**
           * Toggles isOn from true to false and vice versa. Also fires
           * toggleChanged event.
           */
         public void toggle ()
         {
                  on = !on;
                  fireEvent();
         }

         /**



                                          3
* Adds given listener to listener list.
           * @param l
           */
         public void addToggleListener (ToggleListener l)
         {
                  listeners.add(l);
         }

         /**
           * Removes given listener from listener list.
           * @param l
           */
         public void removeToggleListener (ToggleListener l)
         {
                  listeners.remove(l);
         }

         /**
           * Fires toggle event.
           */
         private void fireEvent ()
         {
                  for (ToggleListener l: listeners)
                          l.toggleChanged(this);
         }
}




4 Writing the JComponent
To write a custom UI component in swing, one has to create a class extending JCom-
ponent which is a base class for both standard and custom components (Eckstein et al.,
1998). In this tutorial, we have shown how to create ToggleSwitch and ToggleLED
UI components which share a common model, ToggleModel. The job of component
class which extends abstract JComponent is to tie together model and the UI delegate
together. The custom component does this with the help of Constructor and setUI()
method respectively. It also implements a listener interface (ToggleListener in our
case) which has a stateChanged method (toggleChanged in our case) to notify a state
change. The custom component changes in rendering on the viewport through the UI
delegate, in accordance to the change in state notified by stateChanged method.

         public ToggleSwitch ()
         {
                 init (new ToggleModel());
         }

         public ToggleSwitch (boolean isOn)
         {
                 init (new ToggleModel(isOn));
         }


         public ToggleSwitch (ToggleModel model)
         {
                 init (model);
         }




                                          4
4.1 The toggle switch component
Toggle switch component simulates the real world ‘switch’ having two states ON /
OFF. It changes the state of the LED display, changing its own state when user clicks
on the switch, in similar manner as the real world “switch” changes the state of a bulb
/ LED when toggled.
    There are three ways to instantiate a toggle switch component, allowing a program-
mer to instantiate it with a default ToggleModel (ToggleSwitch()), with a model with
specified on/off state (ToggleSwitch(boolean isOn))and a specified instance of Toggle-
Model. All the three forms of constructors call the init(ToggleModel m) method.

         public ToggleSwitch ()
         {
                 init (new ToggleModel());
         }

         public ToggleSwitch (boolean isOn)
         {
                 init (new ToggleModel(isOn));
         }


         public ToggleSwitch (ToggleModel model)
         {
                 init (model);
         }

    The init inititalises the toggle switch component by setting the given model, reg-
istering the toggle switch component in the model as a listener to listen the toggle
change during user input, initializing the preferred dimension, loading all the icons,
setting the keyboard maps and finally setting up the UI property to current UI delegate
by updateUI property.
private void init (ToggleModel model)
{
        this.model = model;
        model.addToggleListener(this);
        setKeyboardMaps();
        loadIcons();
        setPreferredSize(new Dimension(onIcon.getIconWidth(),
        updateUI();
}

    The setKeyboardMaps method TAB as the forward traversal key and Shift + TAB as
the reverse traversal key. It first creates an instance of HashSets called keystrokes and
keystrokes_back, into which it adds keystrokes for TAB and Shift + TAB respectively.
Then setFocusTraversalKeys method is used to add focus traversal keys by passing
these traversal key type with the HashSet.
private void setKeyboardMaps() {
         Set<AWTKeyStroke> keystrokes = new HashSet<AWTKeyStroke>();
         keystrokes.add(AWTKeyStroke.getAWTKeyStroke("TAB"));
         setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keystrokes);
         Set<AWTKeyStroke> keystrokes_back = new HashSet<AWTKeyStroke>();
         keystrokes_back.add(AWTKeyStroke.getAWTKeyStroke("shift TAB"));
         setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
                                                                       keystrokes_back);
}


                                           5
Here is the complete list of ToggleSwitch.java:
package np.org.mpp.sambad.tutorial.mvc;

import   java.awt.AWTKeyStroke;
import   java.awt.Dimension;
import   java.awt.KeyboardFocusManager;
import   java.util.HashSet;
import   java.util.Set;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.UIManager;

/**
  * A simple toggle switch component.
  * @author Prakash Manandhar
  */
public class ToggleSwitch extends JComponent
implements ToggleListener
{

          /**
           * For serialization.
           */
          private static final long serialVersionUID = 8845972060032351155L;

          // model for this component
          private ToggleModel model;

          private ImageIcon onIcon;
          private ImageIcon offIcon;

          private static final String onIconPath = "res/toggle_on.jpg";
          private static final String offIconPath = "res/toggle_off.jpg";

          /**
            * Creates a default toggle switch with a default constructor.
            */
          public ToggleSwitch ()
          {
                   init (new ToggleModel());
          }

          /**
            * Creates a toggle switch with a model with given initial state.
            * @param isOn
            */
          public ToggleSwitch (boolean isOn)
          {
                   init (new ToggleModel(isOn));
          }

          /**
            * Creates a ToggleSwitch with given model.
            * @param model
            */
          public ToggleSwitch (ToggleModel model)
          {
                   init (model);
          }

          /**


                                         6
* sets the model of this component and adds it to listener
  * list.
  * @param model
  */
private void init (ToggleModel model)
{
          this.model = model;
          model.addToggleListener(this);
          setKeyboardMaps();
          loadIcons();
          setPreferredSize(new Dimension(onIcon.getIconWidth(),
           onIcon.getIconHeight()));
          updateUI();
}

/**
  * Resets the UI property to the current UIdelegate for this
  * component.
  */
public void updateUI ()
{
         setUI((np.org.mpp.sambad.tutorial.mvc.ToggleSwitchUI)UIManager.getUI(this));
         invalidate();
}

/**
  * @return The UIDefaults key used to look up the name of
  * the ComponentUI class that defines the look and feel
  * for this component.
  */
public String getUIClassID() {
         return "np.org.mpp.sambad.tutorial.mvc.ToggleSwitch";
}

/**
  * Returns the model of this (ToggleSwitch) component
  * @return model.
  */
public ToggleModel getModel ()
{
         return model;
}

/**
 * Set TAB as Forward Traversal Key and
 * SHIFT + TAB as Backward Traversal Key
 *
 */

private void setKeyboardMaps() {
        Set<AWTKeyStroke> keystrokes = new HashSet<AWTKeyStroke>();
        keystrokes.add(AWTKeyStroke.getAWTKeyStroke("TAB"));
     setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keystrokes);
        Set<AWTKeyStroke> keystrokes_back = new HashSet<AWTKeyStroke>();
        keystrokes_back.add(AWTKeyStroke.getAWTKeyStroke("shift TAB"));
setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keystrokes_back);
}

/**
 * repaints the component
 */
public void toggleChanged(ToggleModel source) {



                            7
repaint ();
          }

          /**
            * sets onIcon and offIcon to their corresponding path
            */
          private void loadIcons ()
          {
                   onIcon = new ImageIcon(onIconPath);
                   offIcon = new ImageIcon(offIconPath);
          }

          /**
            * Returns Switch-ON image
            * @return onIcon
            */
          ImageIcon getOnIcon ()
          {
                   return onIcon;
          }

          /**
            * Return LED-OFF image
            * @return offIcon
            */
          ImageIcon getOffIcon ()
          {
                   return offIcon;
          }

}



4.2 The LED display component
LED display component simulates the real world LED implementing ToggleListener
as the toggle switch component does. They both implement ToggleListener interface
because both of them displays the same state, i.e. ON / OFF state. Implementation of
LED display component is very similar to that of toggle switch component . Here is
the complete list of ToggleLED.java:
package np.org.mpp.sambad.tutorial.mvc;

import   java.awt.AWTKeyStroke;
import   java.awt.Dimension;
import   java.awt.KeyboardFocusManager;
import   java.util.HashSet;
import   java.util.Set;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.UIManager;

/**
  * A simple toggle LED display component.
  * @author Prakash Manandhar
  */
public class ToggleLED extends JComponent
implements ToggleListener
{



                                         8
/**
 * For serialization.
 */
private static final long serialVersionUID = 8845972060032351155L;

// model for this component
private ToggleModel model;

private ImageIcon onIcon;
private ImageIcon offIcon;

private static final String onIconPath = "res/led_on.jpg";
private static final String offIconPath = "res/led_off.jpg";

/**
  * Creates a default toggle switch with a default constructor.
  */
public ToggleLED ()
{
         init (new ToggleModel());
}

/**
  * Creates a toggle switch with a model with given initial state.
  * @param isOn
  */
public ToggleLED (boolean isOn)
{
         init (new ToggleModel(isOn));
}

/**
  * Creates a ToggleSwitch with given model.
  * @param model
  */
public ToggleLED (ToggleModel model)
{
         init (model);
}

/**
  * sets the model of this component and adds it to listener.
  * @param model
  */
private void init (ToggleModel model)
{
         this.model = model;
         model.addToggleListener(this);
         setKeyboardMaps();
         loadIcons();
         setPreferredSize(new Dimension(onIcon.getIconWidth(),
                                                                        onIcon.getIconHeigh
        updateUI();
}
/**
  * Resets the UI property to the current UIdelegate for this
  * component.
  */
public void updateUI ()
{
         setUI((np.org.mpp.sambad.tutorial.mvc.ToggleLEDUI)UIManager.getUI(this));
         invalidate();



                              9
}
/**
  * @return The UIDefaults key used to look up the name of
  * the swing.plaf.ComponentUI class that defines the look
  * and feel for this component.
  */
public String getUIClassID() {
         return "np.org.mpp.sambad.tutorial.mvc.ToggleLED";
}

/**
  * Returns the model of this (ToggleLED) component
  * @return model.
  */
public ToggleModel getModel ()
{
         return model;
}

/**
  * Set TAB as Forward Traversal Key and
  * SHIFT + TAB as Backward Traversal Key
  *
  */
private void setKeyboardMaps() {
         Set<AWTKeyStroke> keystrokes = new HashSet<AWTKeyStroke>();
         keystrokes.add(AWTKeyStroke.getAWTKeyStroke("TAB"));
         setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keystrokes);
         Set<AWTKeyStroke> keystrokes_back = new HashSet<AWTKeyStroke>();
         keystrokes_back.add(AWTKeyStroke.getAWTKeyStroke("shift TAB"));
         setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keystrokes_back
}

/**
  * repaints the component
  */
public void toggleChanged(ToggleModel source) {
         repaint ();
}

/**
  * sets onIcon and offIcon to their corresponding path
  */
private void loadIcons ()
{
         onIcon = new ImageIcon(onIconPath);
         offIcon = new ImageIcon(offIconPath);
}

/**
  * Returns LED-ON image
  * @return onIcon
  */
ImageIcon getOnIcon ()
{
         return onIcon;
}

/**
 * Return LED-OFF image
 * @return offIcon
 */



                           10
ImageIcon getOffIcon ()
         {
                 return offIcon;
         }

}




5 Writing the UI Delegate
A UI Delegate is a composition of view and controller bundled together. As to our
example, we have two UI delegates namely, ToggleLedUI and ToggleSwitchUI. UI
delegates should have the createUI() method defined that returns the ComponentUI /
UI delegate.
    Since ToggleLedUI does not entertain any user input directly, it has only the view
part, which is used to render (or show) the component on the screen by calling the
paint() method. However, the ToggleSwitchUI has both the controller and the view
parts, because it has to listen to events associated to it.
    View layer of both of these components have simply the paint() method that renders
each of them based on the same underlying model called Toggle Model. The method
paint() creates respective component, define the component’s model, and draws the
component’s image.
    Controller layer in ToggleSwitchUI implements mouse listener and respond to
mouseClick event on the ToggleSwitch component. For this, event listeners are to
be installed onto the component done by installUI() method.
    paint() method for ToggleLedUI delegate:

         public void paint (Graphics g, JComponent c)
         {
                 ToggleLED ts = (ToggleLED)c;
                 ToggleModel model = ts.getModel();
                 Dimension size = ts.getSize();
                 if (model.isOn())
                         drawIcon (g, ts.getOnIcon(), size);
                 else
                         drawIcon (g, ts.getOffIcon(), size);
         }


    installUI() and paint() method for ToggleSwitchUI delegate:

         /**
           * Configures the specified component and creates
           * event listener on the component.
           *
           * @param c
           */
         public void installUI (JComponent c)
         {
                  c.addMouseListener(controller);
         }

         /**
          * Paints the specified component.
          */


                                         11
public void paint (Graphics g, JComponent c)
          {
                  ToggleSwitch ts = (ToggleSwitch)c;
                  ToggleModel model = ts.getModel();
                  Dimension size = ts.getSize();
                  if (model.isOn())
                          drawIcon (g, ts.getOnIcon(), size);
                  else
                          drawIcon (g, ts.getOffIcon(), size);
          }




6 Linking to the model
We have already explained that a single model can be used by different views. But
it doesn’t necessarily mean that the view only needs model. Here we describe how
system’s console output can be linked to the same ToggleModel. With respect to the
state of the model, the console output is being generated so that it acts as a model
listener. Just as we have made the console output to be the model listener of our model,
we can make other application oriented listeners that listen to the same model. For an
example, we can add in a parallel port interfacing class as another listener to this model
and instead of displaying output (states) onto the console, the class sending the output
through the parallel port.
     BitOutputConsole class is the model listener to the Toggle Model. And a link to
the model is created by the addModel() function where BitOutputConsole (our model
listener) registers itself as a listener to the model. It also implements the ToggleListener
class and on doing so, it defines the toggleChanged() method which is called upon by
model whenever the state is changed. The method toggleChanged() displays the state
of all the models registered in the list of models for the BitOutputConsole .
package np.org.mpp.sambad.tutorial.mvc.test;

import java.util.ArrayList;
import java.util.List;

import np.org.mpp.sambad.tutorial.mvc.ToggleListener;
import np.org.mpp.sambad.tutorial.mvc.ToggleModel;

/**
 * Demonstration of ModelListener.
 * @author Prakash Manandhar
 */
public class BitOutputConsole implements ToggleListener {

          List<ToggleModel> models = new ArrayList<ToggleModel>();

          /**
           * Adds Model to the list of models for this listener and
           * adds itself to the listener’s list of the model.
           * @param model
           */

          public void addModel (ToggleModel model)
          {
                  models.add (model);
                  model.addToggleListener(this);
          }



                                            12
/**
          * Writes the state of all LEDs in console.
          * LED ON State = 1, LED OFF State = 0
          */

         public void toggleChanged(ToggleModel source) {
                 System.out.println("");
                 for (ToggleModel m: models)
                         System.out.print(m.isOn()?1:0);
         }

}




7 The main class
The main class in the ToggleComponentTest initializes the UIManager by adding Tog-
gleSwitchUI and ToggleLEDUI, which will be used by the custom components to set
the UI delegate. After that a parent container for the custom components, JFrame is
initialized to whose content pane, 8 pairs of toggle switch and toggle LED sharing a
separate toggle model is added using flowlayout, layout manager. Each pair of toggle
switch and toggle LED sharing a toggle model is instantiated with the help of static
method called addToggleSet. The addToggleSet method takes an integer to calculate
ON / OFF state of the model, a container to which the toggle switch and toggle LED
component pairs are to be added and bit output console, which displays the state bit
of the model on the console. It creates a box container, to which the switch and LED
pair is added, which in turn is added to the container. Finally the main class packs the
added boxes, sets the default close operation and makes the frame visible.
public static void main(String[] args) {
                initUIManager();
                JFrame frame = new JFrame("www.sambad.org MVC Custom Component Tutorial");
                frame.getContentPane().setBackground(Color.WHITE);
                frame.getContentPane().setLayout(new FlowLayout());
                BitOutputConsole bo = new BitOutputConsole();
                for (int i = 0; i < 8; i++)
                        addToggleSet (i, frame.getContentPane(), bo);
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
}

    Here is the complete listing of ToggleComponentTest.java.
package np.org.mpp.sambad.tutorial.mvc.test;

import java.util.ArrayList;
import java.util.List;

import np.org.mpp.sambad.tutorial.mvc.ToggleListener;
import np.org.mpp.sambad.tutorial.mvc.ToggleModel;

/**
 * Demonstration of ModelListener.
 * @author Prakash Manandhar
 */


                                          13
public class BitOutputConsole implements ToggleListener {

          List<ToggleModel> models = new ArrayList<ToggleModel>();

          /**
           * Adds Model to the list of models
           * @param model
           */

          public void addModel (ToggleModel model)
          {
                  models.add (model);
                  model.addToggleListener(this);
          }


          /**
           * writes the state of all LEDs in console.
           * LED ON State = 1, LED OFF State = 0
           */

          public void toggleChanged(ToggleModel source) {
                  System.out.println("");
                  for (ToggleModel m: models)
                          System.out.print(m.isOn()?1:0);
          }

}


    Here is the complete listing of BitOutputConsole.java.


8 Summary
It is easy to write new Java Swing Components from scratch that follow the MVC
architecture by following a few simple steps:

    1. Create the model (reuse existing model if possible)
    2. Create the JComponent, listen to the model and repaint when model changes
    3. Create the ComponentUI, paint based on the state of the model
    4. Create the Controller, listen to mouse and keyboard events; change the model
       when these events occur.


References
Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, and Michael
  Stal. A System of Patterns. John Wiley & Sons, 1996.
Robert Eckstein, Marc Loy, and Dave Wood. Java Swing. O’Reilly, 1998.
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design patterns –
  elements of reusable object-oriented software. Addison Wesley, 1995.
Dean Helman. Model-view-controller. Web, May 1998.

                                          14
Allen Holub. Building user interfaces for object-oriented systems, part 1 – what is an
  object? the theory behind object-oriented user interfaces. Internet Journal/Magazine,
  July 1999.
D. Kruglinski. Inside Visual C++. Microsoft Press, 1995.
Shawn Livermore, Chris Andrade, and Scott Van Vliet. Professional WPF Program-
  ming: .NET Development with the Windows Presentation Foundation. Wiley, 2006.




                                          15

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

Chap1 1.1
Chap1 1.1Chap1 1.1
Chap1 1.1
 
04b swing tutorial
04b swing tutorial04b swing tutorial
04b swing tutorial
 
Java swing
Java swingJava swing
Java swing
 
Java- GUI- Mazenet solution
Java- GUI- Mazenet solutionJava- GUI- Mazenet solution
Java- GUI- Mazenet solution
 
swingbasics
swingbasicsswingbasics
swingbasics
 
Swing
SwingSwing
Swing
 
Graphical User Interface in JAVA
Graphical User Interface in JAVAGraphical User Interface in JAVA
Graphical User Interface in JAVA
 
Java Swing JFC
Java Swing JFCJava Swing JFC
Java Swing JFC
 
Swing and AWT in java
Swing and AWT in javaSwing and AWT in java
Swing and AWT in java
 
GUI Programming with Java
GUI Programming with JavaGUI Programming with Java
GUI Programming with Java
 
Java AWT and Java FX
Java AWT and Java FXJava AWT and Java FX
Java AWT and Java FX
 
Swingpre 150616004959-lva1-app6892
Swingpre 150616004959-lva1-app6892Swingpre 150616004959-lva1-app6892
Swingpre 150616004959-lva1-app6892
 
AWT Packages , Containers and Components
AWT Packages , Containers and ComponentsAWT Packages , Containers and Components
AWT Packages , Containers and Components
 
Android UI Fundamentals part 1
Android UI Fundamentals part 1Android UI Fundamentals part 1
Android UI Fundamentals part 1
 
View groups containers
View groups containersView groups containers
View groups containers
 
The AWT and Swing
The AWT and SwingThe AWT and Swing
The AWT and Swing
 
Swings
SwingsSwings
Swings
 
Enhancement Of Facebook Features
Enhancement Of Facebook FeaturesEnhancement Of Facebook Features
Enhancement Of Facebook Features
 
Java swings
Java swingsJava swings
Java swings
 
java swing
java swingjava swing
java swing
 

Destacado

JavaFX vs AJAX vs Flex
JavaFX vs AJAX vs FlexJavaFX vs AJAX vs Flex
JavaFX vs AJAX vs FlexCraig Dickson
 
Taking HTML5 video a step further
Taking HTML5 video a step furtherTaking HTML5 video a step further
Taking HTML5 video a step furtherSilvia Pfeiffer
 
State of Media Accessibility in HTML5
State of Media Accessibility in HTML5State of Media Accessibility in HTML5
State of Media Accessibility in HTML5Silvia Pfeiffer
 
FINAL DEMO TOPIC
FINAL DEMO TOPICFINAL DEMO TOPIC
FINAL DEMO TOPICbunso18
 
Html5, Native and Platform based Mobile Applications
Html5, Native and Platform based Mobile ApplicationsHtml5, Native and Platform based Mobile Applications
Html5, Native and Platform based Mobile ApplicationsYoss Cohen
 
TKP notes for Java
TKP notes for JavaTKP notes for Java
TKP notes for JavaLynn Langit
 
java-Unit4 chap2- awt controls and layout managers of applet
java-Unit4 chap2- awt controls and layout managers of appletjava-Unit4 chap2- awt controls and layout managers of applet
java-Unit4 chap2- awt controls and layout managers of appletraksharao
 
Java Components and their applicability in Mule Anypoint Studio
Java Components and their applicability in Mule Anypoint StudioJava Components and their applicability in Mule Anypoint Studio
Java Components and their applicability in Mule Anypoint StudioVenkataNaveen Kumar
 
Input and output flow using http and java component
Input and output flow using http and java componentInput and output flow using http and java component
Input and output flow using http and java componentSon Nguyen
 
Native vs. Mobile Web vs. Hybrid Apps for Mobile Development
Native vs. Mobile Web vs. Hybrid Apps for Mobile DevelopmentNative vs. Mobile Web vs. Hybrid Apps for Mobile Development
Native vs. Mobile Web vs. Hybrid Apps for Mobile DevelopmentJason Grigsby
 
Ch11: File System Interface
Ch11: File System InterfaceCh11: File System Interface
Ch11: File System InterfaceAhmar Hashmi
 
Html5 Open Video Tutorial
Html5 Open Video TutorialHtml5 Open Video Tutorial
Html5 Open Video TutorialSilvia Pfeiffer
 
Chapter 10 - File System Interface
Chapter 10 - File System InterfaceChapter 10 - File System Interface
Chapter 10 - File System InterfaceWayne Jones Jnr
 
java swing programming
java swing programming java swing programming
java swing programming Ankit Desai
 

Destacado (20)

Chapter 1 swings
Chapter 1 swingsChapter 1 swings
Chapter 1 swings
 
JavaFX vs AJAX vs Flex
JavaFX vs AJAX vs FlexJavaFX vs AJAX vs Flex
JavaFX vs AJAX vs Flex
 
Html5 vs Flash video
Html5 vs Flash videoHtml5 vs Flash video
Html5 vs Flash video
 
Taking HTML5 video a step further
Taking HTML5 video a step furtherTaking HTML5 video a step further
Taking HTML5 video a step further
 
State of Media Accessibility in HTML5
State of Media Accessibility in HTML5State of Media Accessibility in HTML5
State of Media Accessibility in HTML5
 
FINAL DEMO TOPIC
FINAL DEMO TOPICFINAL DEMO TOPIC
FINAL DEMO TOPIC
 
Html5, Native and Platform based Mobile Applications
Html5, Native and Platform based Mobile ApplicationsHtml5, Native and Platform based Mobile Applications
Html5, Native and Platform based Mobile Applications
 
Java Week6(B) Notepad
Java Week6(B)   NotepadJava Week6(B)   Notepad
Java Week6(B) Notepad
 
File Systems
File SystemsFile Systems
File Systems
 
TKP notes for Java
TKP notes for JavaTKP notes for Java
TKP notes for Java
 
Memory Management
Memory ManagementMemory Management
Memory Management
 
java-Unit4 chap2- awt controls and layout managers of applet
java-Unit4 chap2- awt controls and layout managers of appletjava-Unit4 chap2- awt controls and layout managers of applet
java-Unit4 chap2- awt controls and layout managers of applet
 
Java Components and their applicability in Mule Anypoint Studio
Java Components and their applicability in Mule Anypoint StudioJava Components and their applicability in Mule Anypoint Studio
Java Components and their applicability in Mule Anypoint Studio
 
Input and output flow using http and java component
Input and output flow using http and java componentInput and output flow using http and java component
Input and output flow using http and java component
 
Mule: Java Component
Mule: Java ComponentMule: Java Component
Mule: Java Component
 
Native vs. Mobile Web vs. Hybrid Apps for Mobile Development
Native vs. Mobile Web vs. Hybrid Apps for Mobile DevelopmentNative vs. Mobile Web vs. Hybrid Apps for Mobile Development
Native vs. Mobile Web vs. Hybrid Apps for Mobile Development
 
Ch11: File System Interface
Ch11: File System InterfaceCh11: File System Interface
Ch11: File System Interface
 
Html5 Open Video Tutorial
Html5 Open Video TutorialHtml5 Open Video Tutorial
Html5 Open Video Tutorial
 
Chapter 10 - File System Interface
Chapter 10 - File System InterfaceChapter 10 - File System Interface
Chapter 10 - File System Interface
 
java swing programming
java swing programming java swing programming
java swing programming
 

Similar a Java Swing Custom GUI MVC Component Tutorial

Android Architecture Components
Android Architecture ComponentsAndroid Architecture Components
Android Architecture ComponentsBurhanuddinRashid
 
Observer Pattern Khali Young 2006 Aug
Observer Pattern Khali Young 2006 AugObserver Pattern Khali Young 2006 Aug
Observer Pattern Khali Young 2006 Augmelbournepatterns
 
Java design patterns
Java design patternsJava design patterns
Java design patternsShawn Brito
 
Say bye to Fragments with Conductor & Kotlin
Say bye to Fragments with Conductor & KotlinSay bye to Fragments with Conductor & Kotlin
Say bye to Fragments with Conductor & KotlinMiquel Beltran Febrer
 
Knockoutjs Part 2 Beginners
Knockoutjs Part 2 BeginnersKnockoutjs Part 2 Beginners
Knockoutjs Part 2 BeginnersBhaumik Patel
 
Observer design pattern
Observer design patternObserver design pattern
Observer design patternSara Torkey
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbroncymbron
 
Model View ViewModel
Model View ViewModelModel View ViewModel
Model View ViewModelDoncho Minkov
 
RTL Coding Basics in verilog hardware language
RTL Coding Basics in verilog hardware languageRTL Coding Basics in verilog hardware language
RTL Coding Basics in verilog hardware languageMohammedAbdulAzeem51
 
React Hooks Demystified: How to Effectively Use useCallback and useEffect
React Hooks Demystified: How to Effectively Use useCallback and useEffectReact Hooks Demystified: How to Effectively Use useCallback and useEffect
React Hooks Demystified: How to Effectively Use useCallback and useEffectTien Nguyen
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptKaty Slemon
 
Data binding in AngularJS, from model to view
Data binding in AngularJS, from model to viewData binding in AngularJS, from model to view
Data binding in AngularJS, from model to viewThomas Roch
 
Dependency injection using dagger2
Dependency injection using dagger2Dependency injection using dagger2
Dependency injection using dagger2Javad Hashemi
 
Spring mvc my Faviourite Slide
Spring mvc my Faviourite SlideSpring mvc my Faviourite Slide
Spring mvc my Faviourite SlideDaniel Adenew
 
Oracle Form material
Oracle Form materialOracle Form material
Oracle Form materialRajesh Ch
 
java Unit4 chapter1 applets
java Unit4 chapter1 appletsjava Unit4 chapter1 applets
java Unit4 chapter1 appletsraksharao
 

Similar a Java Swing Custom GUI MVC Component Tutorial (20)

Android Architecture Components
Android Architecture ComponentsAndroid Architecture Components
Android Architecture Components
 
Observer Pattern Khali Young 2006 Aug
Observer Pattern Khali Young 2006 AugObserver Pattern Khali Young 2006 Aug
Observer Pattern Khali Young 2006 Aug
 
Java design patterns
Java design patternsJava design patterns
Java design patterns
 
Say bye to Fragments with Conductor & Kotlin
Say bye to Fragments with Conductor & KotlinSay bye to Fragments with Conductor & Kotlin
Say bye to Fragments with Conductor & Kotlin
 
Ppt on java basics1
Ppt on java basics1Ppt on java basics1
Ppt on java basics1
 
Knockoutjs Part 2 Beginners
Knockoutjs Part 2 BeginnersKnockoutjs Part 2 Beginners
Knockoutjs Part 2 Beginners
 
Observer design pattern
Observer design patternObserver design pattern
Observer design pattern
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbron
 
Model View ViewModel
Model View ViewModelModel View ViewModel
Model View ViewModel
 
RTL Coding Basics in verilog hardware language
RTL Coding Basics in verilog hardware languageRTL Coding Basics in verilog hardware language
RTL Coding Basics in verilog hardware language
 
Ngrx meta reducers
Ngrx meta reducersNgrx meta reducers
Ngrx meta reducers
 
React Hooks Demystified: How to Effectively Use useCallback and useEffect
React Hooks Demystified: How to Effectively Use useCallback and useEffectReact Hooks Demystified: How to Effectively Use useCallback and useEffect
React Hooks Demystified: How to Effectively Use useCallback and useEffect
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
 
Data binding in AngularJS, from model to view
Data binding in AngularJS, from model to viewData binding in AngularJS, from model to view
Data binding in AngularJS, from model to view
 
Dependency injection using dagger2
Dependency injection using dagger2Dependency injection using dagger2
Dependency injection using dagger2
 
Spring mvc my Faviourite Slide
Spring mvc my Faviourite SlideSpring mvc my Faviourite Slide
Spring mvc my Faviourite Slide
 
Robotlegs Introduction
Robotlegs IntroductionRobotlegs Introduction
Robotlegs Introduction
 
Oracle Form material
Oracle Form materialOracle Form material
Oracle Form material
 
Function C++
Function C++ Function C++
Function C++
 
java Unit4 chapter1 applets
java Unit4 chapter1 appletsjava Unit4 chapter1 applets
java Unit4 chapter1 applets
 

Último

Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?SANGHEE SHIN
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfAnna Loughnan Colquhoun
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxYounusS2
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
20200723_insight_release_plan
20200723_insight_release_plan20200723_insight_release_plan
20200723_insight_release_planJamie (Taka) Wang
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServicePicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServiceRenan Moreira de Oliveira
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
GenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation IncGenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation IncObject Automation
 
Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.francesco barbera
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 

Último (20)

Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdf
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptx
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
20200723_insight_release_plan
20200723_insight_release_plan20200723_insight_release_plan
20200723_insight_release_plan
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServicePicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
GenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation IncGenAI and AI GCC State of AI_Object Automation Inc
GenAI and AI GCC State of AI_Object Automation Inc
 
Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.Digital magic. A small project for controlling smart light bulbs.
Digital magic. A small project for controlling smart light bulbs.
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 

Java Swing Custom GUI MVC Component Tutorial

  • 1. Java Swing Custom GUI MVC Component Tutorial Prakash Manandhar, Sagun Dhakhwa, Ishwor Thapa Sambad Project (www.sambad.org), Madan Puraskar Pustakalaya, Nepal July 13, 2006 1 Introduction The Model-View-Controller (MVC) architecture is one of the first widely acclaimed architectures for GUI systems (Gamma et al., 1995;Buschmann et al., 1996). Contem- porary GUI APIs (and even some Web APIs) - like Java Swing, Microsoft Foundation Classes and even its newest incarnation WinFX - are also based on modifications of the MVC architectural pattern (Eckstein et al., 1998; Kruglinski, 1995; Livermore et al., 2006). The MVC does have its fair share of critics, for example Holub [1999] goes so far as to say that MVC is not object-oriented, but we think it is a logical and proven system for beginning GUI system designers and programmers. In this tutorial we take you through creating several simple custom components from scratch using Java Swing as the implementation platform. It is hoped that readers will get a better understanding of the MVC architecture from this document as well as find within it a cook-book for creating MVC style custom GUI components for Java Swing. We implement a simple GUI with toggle switches and LED displays that controls output to the console. Figure 1: Screenshot of finished program 1
  • 2. Figure 2: Model View Controller Architecture views on = true model 2 Model View Controller The Model View Controller Architecture (MVC) is software design architectural pat- tern which breaks an application or just an application’s interface into three types of objects namely, Model, View and Controller (Gamma et al., 1995). Model is the ap- plication object, View is the screen presentation and Control determines how UI reacts to the user input. MVC separates these three components, which used to be coupled together in architectures prior to MVC, yielding more flexibility and reusability. The model encapsulates more than just data and function that operates on it. It represents not just the state of the UI but also how the UI works, making it easier to use real- world modeling (e.g,: Switch and Bulb) techniques in defining the models (Helman, 1998).The model contains the actual state of the UI component. When the state of the UI component changes, the model data should reflect the change. The model then no- tifies all the views which subscribe it, in response the views update themselves. View is responsible for displaying the state of the model on a device. It attaches to a model and render its contents on the device. The controller subscribes both the model and the viewport and knows the type of both in order to translate user input into application response.The views in a MVC can be nested, i.e. they can contain server sub-views. The MVC allows to change the response of the view to the user input without changing the view presentation. A view uses the controller to implement a particual response strategy of the response. 3 Writing the Model Toggle Model represents the state of the component. The model has either the ’ON’ state or ’OFF’ state. It also coordinates with the view by notifying when this model changes the state. 2
  • 3. To represent the state of the model, we simply define a boolean variable called on, which when ’true’ marks the ’ON’ state of the model and ’false’ marks the ’OFF’ state of the model. To maintain link between model and view, model should notify its views with a message that the state has been changed. Here in this example when the state is changed, the Toggle model notifies all its event listeners. Listeners are registered to this model by addToggleListener() call. package np.org.mpp.sambad.tutorial.mvc; import java.util.ArrayList; import java.util.List; /** * A simple model that keeps track whether something is On or Off. * @author Prakash Manandhar */ public class ToggleModel { // model state private boolean on; // list of listeners to this model private List<ToggleListener> listeners = new ArrayList<ToggleListener>(); /** * Default constructors. Initially the model is <em>not on</em>. */ public ToggleModel () { on = false; } /** * Constructor with given intial state. * @param isOn */ public ToggleModel (boolean isOn) { on = isOn; } /** * @return is this toggle on? */ public boolean isOn () { return on; } /** * Toggles isOn from true to false and vice versa. Also fires * toggleChanged event. */ public void toggle () { on = !on; fireEvent(); } /** 3
  • 4. * Adds given listener to listener list. * @param l */ public void addToggleListener (ToggleListener l) { listeners.add(l); } /** * Removes given listener from listener list. * @param l */ public void removeToggleListener (ToggleListener l) { listeners.remove(l); } /** * Fires toggle event. */ private void fireEvent () { for (ToggleListener l: listeners) l.toggleChanged(this); } } 4 Writing the JComponent To write a custom UI component in swing, one has to create a class extending JCom- ponent which is a base class for both standard and custom components (Eckstein et al., 1998). In this tutorial, we have shown how to create ToggleSwitch and ToggleLED UI components which share a common model, ToggleModel. The job of component class which extends abstract JComponent is to tie together model and the UI delegate together. The custom component does this with the help of Constructor and setUI() method respectively. It also implements a listener interface (ToggleListener in our case) which has a stateChanged method (toggleChanged in our case) to notify a state change. The custom component changes in rendering on the viewport through the UI delegate, in accordance to the change in state notified by stateChanged method. public ToggleSwitch () { init (new ToggleModel()); } public ToggleSwitch (boolean isOn) { init (new ToggleModel(isOn)); } public ToggleSwitch (ToggleModel model) { init (model); } 4
  • 5. 4.1 The toggle switch component Toggle switch component simulates the real world ‘switch’ having two states ON / OFF. It changes the state of the LED display, changing its own state when user clicks on the switch, in similar manner as the real world “switch” changes the state of a bulb / LED when toggled. There are three ways to instantiate a toggle switch component, allowing a program- mer to instantiate it with a default ToggleModel (ToggleSwitch()), with a model with specified on/off state (ToggleSwitch(boolean isOn))and a specified instance of Toggle- Model. All the three forms of constructors call the init(ToggleModel m) method. public ToggleSwitch () { init (new ToggleModel()); } public ToggleSwitch (boolean isOn) { init (new ToggleModel(isOn)); } public ToggleSwitch (ToggleModel model) { init (model); } The init inititalises the toggle switch component by setting the given model, reg- istering the toggle switch component in the model as a listener to listen the toggle change during user input, initializing the preferred dimension, loading all the icons, setting the keyboard maps and finally setting up the UI property to current UI delegate by updateUI property. private void init (ToggleModel model) { this.model = model; model.addToggleListener(this); setKeyboardMaps(); loadIcons(); setPreferredSize(new Dimension(onIcon.getIconWidth(), updateUI(); } The setKeyboardMaps method TAB as the forward traversal key and Shift + TAB as the reverse traversal key. It first creates an instance of HashSets called keystrokes and keystrokes_back, into which it adds keystrokes for TAB and Shift + TAB respectively. Then setFocusTraversalKeys method is used to add focus traversal keys by passing these traversal key type with the HashSet. private void setKeyboardMaps() { Set<AWTKeyStroke> keystrokes = new HashSet<AWTKeyStroke>(); keystrokes.add(AWTKeyStroke.getAWTKeyStroke("TAB")); setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keystrokes); Set<AWTKeyStroke> keystrokes_back = new HashSet<AWTKeyStroke>(); keystrokes_back.add(AWTKeyStroke.getAWTKeyStroke("shift TAB")); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keystrokes_back); } 5
  • 6. Here is the complete list of ToggleSwitch.java: package np.org.mpp.sambad.tutorial.mvc; import java.awt.AWTKeyStroke; import java.awt.Dimension; import java.awt.KeyboardFocusManager; import java.util.HashSet; import java.util.Set; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.UIManager; /** * A simple toggle switch component. * @author Prakash Manandhar */ public class ToggleSwitch extends JComponent implements ToggleListener { /** * For serialization. */ private static final long serialVersionUID = 8845972060032351155L; // model for this component private ToggleModel model; private ImageIcon onIcon; private ImageIcon offIcon; private static final String onIconPath = "res/toggle_on.jpg"; private static final String offIconPath = "res/toggle_off.jpg"; /** * Creates a default toggle switch with a default constructor. */ public ToggleSwitch () { init (new ToggleModel()); } /** * Creates a toggle switch with a model with given initial state. * @param isOn */ public ToggleSwitch (boolean isOn) { init (new ToggleModel(isOn)); } /** * Creates a ToggleSwitch with given model. * @param model */ public ToggleSwitch (ToggleModel model) { init (model); } /** 6
  • 7. * sets the model of this component and adds it to listener * list. * @param model */ private void init (ToggleModel model) { this.model = model; model.addToggleListener(this); setKeyboardMaps(); loadIcons(); setPreferredSize(new Dimension(onIcon.getIconWidth(), onIcon.getIconHeight())); updateUI(); } /** * Resets the UI property to the current UIdelegate for this * component. */ public void updateUI () { setUI((np.org.mpp.sambad.tutorial.mvc.ToggleSwitchUI)UIManager.getUI(this)); invalidate(); } /** * @return The UIDefaults key used to look up the name of * the ComponentUI class that defines the look and feel * for this component. */ public String getUIClassID() { return "np.org.mpp.sambad.tutorial.mvc.ToggleSwitch"; } /** * Returns the model of this (ToggleSwitch) component * @return model. */ public ToggleModel getModel () { return model; } /** * Set TAB as Forward Traversal Key and * SHIFT + TAB as Backward Traversal Key * */ private void setKeyboardMaps() { Set<AWTKeyStroke> keystrokes = new HashSet<AWTKeyStroke>(); keystrokes.add(AWTKeyStroke.getAWTKeyStroke("TAB")); setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keystrokes); Set<AWTKeyStroke> keystrokes_back = new HashSet<AWTKeyStroke>(); keystrokes_back.add(AWTKeyStroke.getAWTKeyStroke("shift TAB")); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keystrokes_back); } /** * repaints the component */ public void toggleChanged(ToggleModel source) { 7
  • 8. repaint (); } /** * sets onIcon and offIcon to their corresponding path */ private void loadIcons () { onIcon = new ImageIcon(onIconPath); offIcon = new ImageIcon(offIconPath); } /** * Returns Switch-ON image * @return onIcon */ ImageIcon getOnIcon () { return onIcon; } /** * Return LED-OFF image * @return offIcon */ ImageIcon getOffIcon () { return offIcon; } } 4.2 The LED display component LED display component simulates the real world LED implementing ToggleListener as the toggle switch component does. They both implement ToggleListener interface because both of them displays the same state, i.e. ON / OFF state. Implementation of LED display component is very similar to that of toggle switch component . Here is the complete list of ToggleLED.java: package np.org.mpp.sambad.tutorial.mvc; import java.awt.AWTKeyStroke; import java.awt.Dimension; import java.awt.KeyboardFocusManager; import java.util.HashSet; import java.util.Set; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.UIManager; /** * A simple toggle LED display component. * @author Prakash Manandhar */ public class ToggleLED extends JComponent implements ToggleListener { 8
  • 9. /** * For serialization. */ private static final long serialVersionUID = 8845972060032351155L; // model for this component private ToggleModel model; private ImageIcon onIcon; private ImageIcon offIcon; private static final String onIconPath = "res/led_on.jpg"; private static final String offIconPath = "res/led_off.jpg"; /** * Creates a default toggle switch with a default constructor. */ public ToggleLED () { init (new ToggleModel()); } /** * Creates a toggle switch with a model with given initial state. * @param isOn */ public ToggleLED (boolean isOn) { init (new ToggleModel(isOn)); } /** * Creates a ToggleSwitch with given model. * @param model */ public ToggleLED (ToggleModel model) { init (model); } /** * sets the model of this component and adds it to listener. * @param model */ private void init (ToggleModel model) { this.model = model; model.addToggleListener(this); setKeyboardMaps(); loadIcons(); setPreferredSize(new Dimension(onIcon.getIconWidth(), onIcon.getIconHeigh updateUI(); } /** * Resets the UI property to the current UIdelegate for this * component. */ public void updateUI () { setUI((np.org.mpp.sambad.tutorial.mvc.ToggleLEDUI)UIManager.getUI(this)); invalidate(); 9
  • 10. } /** * @return The UIDefaults key used to look up the name of * the swing.plaf.ComponentUI class that defines the look * and feel for this component. */ public String getUIClassID() { return "np.org.mpp.sambad.tutorial.mvc.ToggleLED"; } /** * Returns the model of this (ToggleLED) component * @return model. */ public ToggleModel getModel () { return model; } /** * Set TAB as Forward Traversal Key and * SHIFT + TAB as Backward Traversal Key * */ private void setKeyboardMaps() { Set<AWTKeyStroke> keystrokes = new HashSet<AWTKeyStroke>(); keystrokes.add(AWTKeyStroke.getAWTKeyStroke("TAB")); setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keystrokes); Set<AWTKeyStroke> keystrokes_back = new HashSet<AWTKeyStroke>(); keystrokes_back.add(AWTKeyStroke.getAWTKeyStroke("shift TAB")); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keystrokes_back } /** * repaints the component */ public void toggleChanged(ToggleModel source) { repaint (); } /** * sets onIcon and offIcon to their corresponding path */ private void loadIcons () { onIcon = new ImageIcon(onIconPath); offIcon = new ImageIcon(offIconPath); } /** * Returns LED-ON image * @return onIcon */ ImageIcon getOnIcon () { return onIcon; } /** * Return LED-OFF image * @return offIcon */ 10
  • 11. ImageIcon getOffIcon () { return offIcon; } } 5 Writing the UI Delegate A UI Delegate is a composition of view and controller bundled together. As to our example, we have two UI delegates namely, ToggleLedUI and ToggleSwitchUI. UI delegates should have the createUI() method defined that returns the ComponentUI / UI delegate. Since ToggleLedUI does not entertain any user input directly, it has only the view part, which is used to render (or show) the component on the screen by calling the paint() method. However, the ToggleSwitchUI has both the controller and the view parts, because it has to listen to events associated to it. View layer of both of these components have simply the paint() method that renders each of them based on the same underlying model called Toggle Model. The method paint() creates respective component, define the component’s model, and draws the component’s image. Controller layer in ToggleSwitchUI implements mouse listener and respond to mouseClick event on the ToggleSwitch component. For this, event listeners are to be installed onto the component done by installUI() method. paint() method for ToggleLedUI delegate: public void paint (Graphics g, JComponent c) { ToggleLED ts = (ToggleLED)c; ToggleModel model = ts.getModel(); Dimension size = ts.getSize(); if (model.isOn()) drawIcon (g, ts.getOnIcon(), size); else drawIcon (g, ts.getOffIcon(), size); } installUI() and paint() method for ToggleSwitchUI delegate: /** * Configures the specified component and creates * event listener on the component. * * @param c */ public void installUI (JComponent c) { c.addMouseListener(controller); } /** * Paints the specified component. */ 11
  • 12. public void paint (Graphics g, JComponent c) { ToggleSwitch ts = (ToggleSwitch)c; ToggleModel model = ts.getModel(); Dimension size = ts.getSize(); if (model.isOn()) drawIcon (g, ts.getOnIcon(), size); else drawIcon (g, ts.getOffIcon(), size); } 6 Linking to the model We have already explained that a single model can be used by different views. But it doesn’t necessarily mean that the view only needs model. Here we describe how system’s console output can be linked to the same ToggleModel. With respect to the state of the model, the console output is being generated so that it acts as a model listener. Just as we have made the console output to be the model listener of our model, we can make other application oriented listeners that listen to the same model. For an example, we can add in a parallel port interfacing class as another listener to this model and instead of displaying output (states) onto the console, the class sending the output through the parallel port. BitOutputConsole class is the model listener to the Toggle Model. And a link to the model is created by the addModel() function where BitOutputConsole (our model listener) registers itself as a listener to the model. It also implements the ToggleListener class and on doing so, it defines the toggleChanged() method which is called upon by model whenever the state is changed. The method toggleChanged() displays the state of all the models registered in the list of models for the BitOutputConsole . package np.org.mpp.sambad.tutorial.mvc.test; import java.util.ArrayList; import java.util.List; import np.org.mpp.sambad.tutorial.mvc.ToggleListener; import np.org.mpp.sambad.tutorial.mvc.ToggleModel; /** * Demonstration of ModelListener. * @author Prakash Manandhar */ public class BitOutputConsole implements ToggleListener { List<ToggleModel> models = new ArrayList<ToggleModel>(); /** * Adds Model to the list of models for this listener and * adds itself to the listener’s list of the model. * @param model */ public void addModel (ToggleModel model) { models.add (model); model.addToggleListener(this); } 12
  • 13. /** * Writes the state of all LEDs in console. * LED ON State = 1, LED OFF State = 0 */ public void toggleChanged(ToggleModel source) { System.out.println(""); for (ToggleModel m: models) System.out.print(m.isOn()?1:0); } } 7 The main class The main class in the ToggleComponentTest initializes the UIManager by adding Tog- gleSwitchUI and ToggleLEDUI, which will be used by the custom components to set the UI delegate. After that a parent container for the custom components, JFrame is initialized to whose content pane, 8 pairs of toggle switch and toggle LED sharing a separate toggle model is added using flowlayout, layout manager. Each pair of toggle switch and toggle LED sharing a toggle model is instantiated with the help of static method called addToggleSet. The addToggleSet method takes an integer to calculate ON / OFF state of the model, a container to which the toggle switch and toggle LED component pairs are to be added and bit output console, which displays the state bit of the model on the console. It creates a box container, to which the switch and LED pair is added, which in turn is added to the container. Finally the main class packs the added boxes, sets the default close operation and makes the frame visible. public static void main(String[] args) { initUIManager(); JFrame frame = new JFrame("www.sambad.org MVC Custom Component Tutorial"); frame.getContentPane().setBackground(Color.WHITE); frame.getContentPane().setLayout(new FlowLayout()); BitOutputConsole bo = new BitOutputConsole(); for (int i = 0; i < 8; i++) addToggleSet (i, frame.getContentPane(), bo); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } Here is the complete listing of ToggleComponentTest.java. package np.org.mpp.sambad.tutorial.mvc.test; import java.util.ArrayList; import java.util.List; import np.org.mpp.sambad.tutorial.mvc.ToggleListener; import np.org.mpp.sambad.tutorial.mvc.ToggleModel; /** * Demonstration of ModelListener. * @author Prakash Manandhar */ 13
  • 14. public class BitOutputConsole implements ToggleListener { List<ToggleModel> models = new ArrayList<ToggleModel>(); /** * Adds Model to the list of models * @param model */ public void addModel (ToggleModel model) { models.add (model); model.addToggleListener(this); } /** * writes the state of all LEDs in console. * LED ON State = 1, LED OFF State = 0 */ public void toggleChanged(ToggleModel source) { System.out.println(""); for (ToggleModel m: models) System.out.print(m.isOn()?1:0); } } Here is the complete listing of BitOutputConsole.java. 8 Summary It is easy to write new Java Swing Components from scratch that follow the MVC architecture by following a few simple steps: 1. Create the model (reuse existing model if possible) 2. Create the JComponent, listen to the model and repaint when model changes 3. Create the ComponentUI, paint based on the state of the model 4. Create the Controller, listen to mouse and keyboard events; change the model when these events occur. References Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, and Michael Stal. A System of Patterns. John Wiley & Sons, 1996. Robert Eckstein, Marc Loy, and Dave Wood. Java Swing. O’Reilly, 1998. Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design patterns – elements of reusable object-oriented software. Addison Wesley, 1995. Dean Helman. Model-view-controller. Web, May 1998. 14
  • 15. Allen Holub. Building user interfaces for object-oriented systems, part 1 – what is an object? the theory behind object-oriented user interfaces. Internet Journal/Magazine, July 1999. D. Kruglinski. Inside Visual C++. Microsoft Press, 1995. Shawn Livermore, Chris Andrade, and Scott Van Vliet. Professional WPF Program- ming: .NET Development with the Windows Presentation Foundation. Wiley, 2006. 15