    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: What Is Swing?</title>
        <link>https://members.accu.org/index.php/articles/1132</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + CVu Journal Vol 13, #4 - Aug 2001</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c119/">134</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-119/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+119/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;What Is Swing?</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 August 2001 13:15:47 +01:00 or Fri, 03 August 2001 13:15:47 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e24" id="d0e24"></a>The Root
Pane</h2>
</div>
<p>Layout managers and child components are never added to a
<tt class="literal">JFrame</tt> directly. Instead you must access
the content pane of the <tt class="literal">JFrame</tt> and add any
layout managers and child components to the ContentPane object.</p>
<p>Why is this so? Well behind the scenes the <tt class=
"literal">JRootPane</tt> is used internally by all the top-level
Swing containers: <tt class="literal">JWindow</tt>, <tt class=
"literal">JFrame</tt>, <tt class="literal">JDialog</tt>, <tt class=
"literal">JApplet</tt>, and <tt class=
"literal">JInternalFrame</tt>. The <tt class=
"literal">JRootPane</tt> is a special container that manages a
fixed ordered layout. It manages a content pane, a layered list of
children and potentially a menu bar. The <tt class=
"literal">JRootPane</tt> prohibits child components from being
added directly to itself. Instead you must add any new components
to the content pane it manages. This is the literal reason why. The
practical reason is that <tt class="literal">JRootPane</tt> is one
of the family of different panes, which you can think of as panes
in a window, in Swing e.g. <tt class="literal">JScrollPane</tt>,
<tt class="literal">JlayeredPane</tt>, <tt class=
"literal">JTabbedPane</tt>. The root pane is a special pane,
because it designed to manage the various panes of a top-level
component. Each root pane has a glass pane, a layered pane, a
content Pane, and optionally a menu bar.</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>The glass pane is a <tt class="literal">JComponent</tt>, which
sits at the top of the window pane-stack. It is normally
transparent, and because it is the highest component, it can
potentially trap all input events. It is not normally used except
for advanced applications.</p>
</li>
<li>
<p>The layered pane is a <tt class="literal">JLayeredPane</tt>,
which sits one level beneath the glass pane. It manages a list of
<tt class="literal">JInternalFrame</tt> objects, which is a
component class that support Multiple Document Interface
applications in Swing, exactly like Microsoft Office
applications.</p>
</li>
<li>
<p>The content pane is a specific container, say a <tt class=
"literal">JPanel</tt>, which sits one level beneath the layered
pane. The application adds child components to this pane.</p>
</li>
<li>
<p>The menu bar is an optional slot for a <tt class=
"literal">JMenuBar</tt> component, which sits at the same level as
the content pane. The root pane automatically reserves a space for
the <tt class="literal">JMenuBar</tt> if it is used.</p>
</li>
</ol>
</div>
<p>Normally you never have to access the root pane container
directly, because the top level components, like <tt class=
"literal">JFrame</tt> for instance, provide convenience methods
such as <tt class="literal">getContentPane()</tt>, <tt class=
"literal">getMenuBar()</tt>, and <tt class=
"literal">setMenuBar()</tt> .</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e118" id="d0e118"></a>Actions</h2>
</div>
<p>Swing introduces a brand new interface class called <tt class=
"literal">Action</tt>. It basically encapsulates the older
<tt class="literal">java.awt.event.ActionListener</tt> into a more
useful interface. An action is an association between an action
listener, its corresponding behaviour, a list of attributes, and a
known public name. You can think of an <tt class=
"literal">Action</tt> almost like a finite state, because it
represents a single behaviour in an application. For instance
saving a file, printing a file, or opening an XML document and
transforming it into useful content like HTML using a XML
stylesheet. The <tt class="literal">Action</tt> class extends the
<tt class="literal">ActionListener</tt> and introduces the ability
to enable or disable the action, to add and remove a property
change listener to listen to events fired by the action.</p>
<pre class="programlisting">
public interface Action extends java.awt.event.ActionListener
{
  public void addPropertyChangeListener(
      java.beans.PropertyChangeListener listener);
  public void removePropertyChangeListener(
      java.beans.PropertyChangeListener listener);
  public Object getValue(String key);
  public void putValue(String key, Object value);
  public boolean isEnabled();
  public void setEnabled(boolean flag);
  public final String DEFAULT;
  public final String NAME;
  public final String LONG_DESCRIPTION;
  public final String SHORT_DESCRIPTION;
  public final String SMALL_ICON;
}
</pre>
<p>The interface also defines static string constants to represent
standard attribute for all actions. Actions maintain a map of name
attributes and values. If, for example, you want to find the icon
of the action, you would query the method <tt class=
"literal">getValue()</tt> with the key <tt class=
"literal">SMALL_ICON</tt>. The basic idea of the overall interface
is to allow any action listener to respond to feedback. This is
tremendously useful, because we only need one instance of the
behaviour. Say to terminate the application we only need to create
one <tt class="literal">QuitAction</tt> object and register it many
components. Fortunately Swing provides an abstract base class
called <tt class="literal">AbstractAction</tt>, which implements
the methods in the interface except for the <tt class=
"literal">actionPerformed()</tt>. We, then, don't have to create
<tt class="literal">Action</tt> object entirely from scratch every
time.</p>
<pre class="programlisting">
public abstract class AbstractAction extends javax.swing.Action
{
  public AbstractAction();
  public AbstractAction(String name);
  public AbstractAction(String name, Icon icon);
  public abstract void actionPerformed(ActionEvent evt);
  ...
}
</pre>
<p>Enough of theory lets look at the second version of our Swing
preferences application. The first task is to copy the file
<tt class="filename">PrefencesApp1.java</tt> to a new Java source
file called <tt class="filename">PreferencesApp2.java</tt>. The new
object class, <tt class="literal">PreferenceApps2</tt>, still
subclasses the <tt class="literal">JFrame</tt> class but no longer
implements the <tt class="literal">ActionListener</tt> interface
directly. Instead we will use inner classes and <tt class=
"literal">Action</tt>s. Also we remove the old <tt class=
"literal">actionPerformed()</tt> method. We are also introducing
new variables and declaration at the top of the file for <tt class=
"literal">AbstractAction</tt>s and two <tt class=
"literal">JLabel</tt>s widget see later.</p>
<pre class="programlisting">
public class PreferencesApp2 extends JFrame 
{
  protected JButton  bt_add;
  protected JButton  bt_remove;
  protected JButton  bt_quit;
  protected JList  list_availableFont;
  protected JList  list_configFont;
  protected JLabel  previewLower;
  protected JLabel  previewUpper;
  protected AbstractAction quitAction;
  protected AbstractAction addAction;
  protected AbstractAction removeAction;
  public PreferencesApp2(String title){ ... }
  ...
}
</pre>
<p>We create our first <tt class="literal">Action</tt>, called
<tt class="literal">QuitAction</tt> as an inner nested class. This
is very simple action that terminates the application when it is
invoked.</p>
<pre class="programlisting">
public class PreferencesApp2 extends JFrame 
{
  ...
// INNER CLASSES HERE! At the end of the class definition
  protected class QuitAction extends AbstractAction{
    public QuitAction(){
      super(&quot;Quit&quot;);
      putValue(SHORT_DESCRIPTION, &quot;Stop This Application&quot;);
    }
    public void actionPerformed(ActionEvent evt){
      System.out.println(&quot;Goodbye.&quot;);
      System.exit(0);
    }
  }
}
</pre>
<p>Since <tt class="literal">Action</tt> class is an <tt class=
"literal">ActionListener</tt> we can register it directly with the
<tt class="literal">JButton</tt>s by calling <tt class=
"literal">addActionListener(ActionListener)</tt> method.</p>
<p>To finish up this section we need to register our new actions
with their respective <tt class="literal">JButton</tt>s.</p>
<pre class="programlisting">
public class PreferencesApp2 extends JFrame {
  ...
  public PreferencesApp2(String title) {
    super(title);
// First create our actions we need them later
    quitAction = new QuitAction();
    addAction = new AddAction();
    removeAction = new RemoveAction();
    ...
// --------------------------------------------
// User interface is complete up to this point
// --------------------------------------------
    bt_quit.addActionListener(quitAction);
    bt_add.addActionListener(addAction);
    bt_remove.addActionListener(removeAction);
  }
  ...
}
</pre>
<p>Now we have to define the next two actions <tt class=
"literal">AddAction</tt> and <tt class="literal">RemoveAction</tt>
inner classes. But before we do that, we must make a slight
detour.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e232" id=
"d0e232"></a>ListModel</h2>
</div>
<p>As was explained previously, Swing is built on the
MODEL-VIEW-CONTROLLER architecture. The majority of Swing
components support an underlying data model interface or abstract
class or both. Thus the <tt class="literal">JList</tt> component
expects to interact with a <tt class="literal">ListModel</tt>
interface class, which has a very simple interface.</p>
<pre class="programlisting">
public interface ListModel{
  public void addListDataListener(javax.swing.event.ListDataListener listener);
  public void removeListDataListener(javax.swing.event.ListDataListener listener);
  public Object getElementAt(int index);
  public int getSize();
}
</pre>
<p>The list model like the action interface beforehand provides a
way of getting feedback from the model, whenever there is change to
the data in the model, events are fired to any registered
listeners. In the list model this feedback takes place by
registering a <tt class="literal">ListDataListener</tt> object with
the model. This interface represents the bare minimum features of a
read-only [immutable] list model. By itself the <tt class=
"literal">ListModel</tt>, then, is not very useful. Swing, however,
does provide a more extensive object class called <tt class=
"literal">DefaultListModel</tt>. The class shares many method
signatures, thankfully, with the <tt class=
"literal">java.util.Vector</tt> class and the much newer <tt class=
"literal">java.util.ArrayList</tt> Java Collections Framework
class. There are far too many methods to list to here but the
essential ones that we use in the preferences application are shown
below.</p>
<pre class="programlisting">
public class DefaultListModel  extends javax.swing.AbstractListModel{
  public boolean isEmpty();
  public int getSize();
  public void addElement(Object element);
  public void removeElement(Object element);
  public void removeElementAt(int index);
  public void removeAllElements();
  public Object elementAt(int index);
// alias for getElementAt()
  public Object getElementAt(int index);
  public boolean contains(Object element);
  public int indexOf(Object element);
  public java.util.Enumerator elements();
// Java Collections Interface JDK1.2
  public void add(Object element);
  public Object add(int index);
  public Object add(int index, Object element);
  public Object remove(int index);
  public Object get(int index);
  public void clear();
}
</pre>
<p>And now we go on to implementing our remaining abstract actions.
<tt class="literal">JList</tt> provides a method to get the
currently selected item in the list, if any. It is called
<tt class="literal">getSelectedValue()</tt> and returns an
<tt class="literal">Object</tt> or <tt class="literal">null</tt> if
there was no item selected at all. We can use this method to
implement the <tt class="literal">AddAction</tt> right now. We
effectively transfer one element from one source <tt class=
"literal">ListModel</tt> to the target.</p>
<pre class="programlisting">
protected class AddAction extends AbstractAction{
  public AddAction(){
    super(&quot;Add&quot;);
    putValue(SHORT_DESCRIPTION, &quot;Add Selected Font&quot;);
  }
  public void actionPerformed(ActionEvent evt){
    String fontChosen = (String)list_availableFont.getSelectedValue();
    if (fontChosen != null){
      DefaultListModel availModel = (DefaultListModel)list_availableFont.getModel();
      DefaultListModel configModel = (DefaultListModel)list_configFont.getModel();
      if(!configModel.contains(fontChosen)){
        configModel.addElement(fontChosen);
        availModel.removeElement(fontChosen);
      }
    }
  }
}
</pre>
<p>We, first, check that the available font has a selected item,
which is the name of the font family. We get the <tt class=
"literal">ListModel</tt> type objects from the respective
<tt class="literal">JList</tt> objects. (We know that they are
really <tt class="literal">DefaultListModel</tt> objects, since we
created and add in the constructor, therefore we can safely cast.)
We make sure that the font family has not already been added to
user configuration list. Finally if has not been, we transfer it.
Delete the font family from the available list and add it to the
user configuration list. Job done.</p>
<p>The <tt class="literal">RemoveAction</tt> is a mirror image of
the <tt class="literal">AddAction</tt> inner class. We just swap
the source and target list model objects around in the source
code.</p>
<pre class="programlisting">
protected class RemoveAction extends AbstractAction {
  public RemoveAction(){
    super(&quot;Remove&quot;);
    putValue(SHORT_DESCRIPTION, &quot;Remove Selected Font&quot;);
  }
  public void actionPerformed(ActionEvent evt){
    String fontChosen = (String)list_configFont.getSelectedValue();
    if(fontChosen != null){
      DefaultListModel configModel = (DefaultListModel)list_configFont.getModel();
      DefaultListModel availModel = (DefaultListModel)list_availableFont.getModel();
      if (!availModel.contains(fontChosen)){
        availModel.addElement(fontChosen);
        configModel.removeElement(fontChosen);
      }
    }
  }
}
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e307" id=
"d0e307"></a>ListSelectionListener and Event</h2>
</div>
<p>If you want to find out which items where selected in a
<tt class="literal">JList</tt>. You must create a <tt class=
"literal">ListSelectionListener</tt> object class and interpret the
<tt class="literal">ListSelectionEvent</tt>.</p>
<p>The interface for the <tt class=
"literal">ListSelectionListener</tt> is simply:</p>
<pre class="programlisting">
public interface ListSelectionListener  extends java.util.EventListener{
  public abstract void valueChanged(ListSelectionEvent evt);
}
</pre>
<p>The only method that we are contracted to define is <tt class=
"literal">valueChanged()</tt>. The <tt class=
"literal">ListSelectionEvent</tt> class is generated by the
<tt class="literal">JList</tt> class, or more correctly its
internal <tt class="literal">ListSelectionModel</tt> object,
whenever the list selection data changes:</p>
<pre class="programlisting">
public class ListSelectionEvent  extends java.util.EventObject{
// Constructor
  public ListSelectionEvent(Object source, int firstIndex, int lastIndex, boolean adjusting);
// Methods
  public int getFirstIndex();
  public int getLastIndex();
  public boolean getValueIsAdjusting();
}
</pre>
<p>The <tt class="literal">getFirstIndex()</tt> and <tt class=
"literal">getLastIndex()</tt> method return the first and last
indices of the list model that may have had their selection changed
respectively. The <tt class="literal">ListSelectionEvent</tt> does
not transmit the items that have been selected or unselected
themselves. Therefore in order to find out what the selected items
are, we have to inquire about the items directly from the
<tt class="literal">JList</tt> or the data model. Incidentally, the
source of the event can always be found by calling the <tt class=
"literal">getSource()</tt> method of the superclass <tt class=
"literal">EventObject</tt>. The last method <tt class=
"literal">getValueIsAdjusting()</tt> returns <tt class=
"literal">true</tt> if the event is one of a series of rapid-fire
events. (You may get an event-train if you set a <tt class=
"literal">JList</tt> to allow multiple selections. See the Java
documentation on the <tt class="literal">JList</tt> method
<tt class="literal">setSelectionMode()</tt> for more information.)
In other words the list selection event can be fired multiple times
in succession, so be careful to check that this method returns
false before you do something permanent.</p>
<p>Finally to register a list selection listener object we call the
<tt class="literal">JList</tt> method :<tt class=
"literal">addListSelectionListener(ListSelectionListerner)</tt>.</p>
<p>We, now, can make use of the information to build some extra
functionality into the preferences application. We would like to
allow the user to see the preview of the font before he or she
added it to first user configuration. We can display a preview of
the font family at a fixed size and weight. Whenever the selection
in either of the list components changes we arrange to change the
font of the preview labels. We can make use of those two <tt class=
"literal">JLabel</tt> declarations that we set aside previously. We
write a simple text string into both labels and have one display
the content in upper case and the other one in lower case. To make
this happen we add some more lines to the <tt class=
"literal">PreferencesApp2</tt> constructor where the user interface
is created:</p>
<pre class="programlisting">
public class PreferencesApp2 extends JFrame {
  ...
  public PreferencesApp2(String title){
    super(title);
    ...
// Add another vertical box to preview the currently selected list font as two labels widgets
    Box box2 = Box.createVerticalBox();
    container.add(box2, BorderLayout.SOUTH);
    previewLower = new JLabel(&quot;the quick brown fox jumps over the lazy dog&quot;);
    previewLower.setFont(new Font(&quot;Arial&quot;, Font.PLAIN, 18));
    box2.add(Box.createVerticalStrut(20));
    box2.add(previewLower);
    previewUpper = new JLabel(&quot;THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG&quot;);
      previewUpper.setFont(new Font(&quot;Arial&quot;, Font.PLAIN, 18));
    box2.add(Box.createVerticalStrut(2));
    box2.add(previewUpper);
// Add a preview font list selection listener to each list
    PreviewFontHandler previewHandler = new PreviewFontHandler();
    list_availableFont.addListSelectionListener(previewHandler);
    list_configFont.addListSelectionListener(previewHandler);
// User interface is complete up to this point
    ...
  }
  ...
}
</pre>
<p>The only part left now is to define the <tt class=
"literal">PreviewFontHandler</tt> the custom <tt class=
"literal">ListSelectionListener</tt> inner class. The <tt class=
"literal">valueChanged()</tt> method, first, makes sure that the
event is the last of the series of rapid-fire events. Having
retrieved the chosen font family from the affected <tt class=
"literal">JList</tt> component, the method proceeds to change the
font of the preview label based on the chosen font family.</p>
<pre class="programlisting">
protected class PreviewFontHandler implements ListSelectionListener{
  public void valueChanged(ListSelectionEvent evt) {
    if(evt.getValueIsAdjusting()) return; // Ignore rapid-fire events
// Check the event source is really a JList
    Object source = evt.getSource();
    if(source == list_availableFont || source == list_configFont){
      JList listGUI = (JList)source;
      String fontChosen = (String)listGUI.getSelectedValue();
      Font font = new Font(fontChosen, Font.PLAIN, 18);
      previewUpper.setFont(font);
      previewLower.setFont(font);
    }
  }
}
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e413" id="d0e413"></a>MenuBars ,
MenuItems, and Menus</h2>
</div>
<p>The top-level components in Swing can accept an optionally
<tt class="literal">JMenuBar</tt> component. To set a menu bar for
a <tt class="literal">JFrame</tt> component you call the <tt class=
"literal">setJMenuBar(JmenuBar)</tt> method. Creating a menu bar
component is very easy. You just call it with a default
constructor. A menu bar allows a pull down menu to be added with
the method <tt class="literal">add(JMenu)</tt> and removed with the
method <tt class="literal">remove(JMenu)</tt>. The menus are laid
out by a special layout manager, which arranges the menus in order
of their addition from left to right. A special slot, on the far
right hand side, is reserved for a help pull down menu. You can
designate which menu is the help menu with the method <tt class=
"literal">setHelpMenu(JMenu)</tt>. The <tt class=
"literal">JMenuBar</tt> subclasses from <tt class=
"literal">JComponent</tt> class.</p>
<p><tt class="literal">JMenuBar</tt> also implements the <tt class=
"literal">MenuElement</tt> interface which contracts all the
methods that menu components must define in order to handle
navigation and event handling in a standard way.</p>
<pre class="programlisting">
public JMenuBar extends JComponent implements MenuElement{
// Constructors
  public JMenuBar();
// methods
  public add(JMenu menu);
  public remove(JMenu menu);
  public setHelpMenu(JMenu menu);
  public JmenuItem getHelpMenu();
  ...
}
</pre>
<p>The individual menu component is <tt class=
"literal">JMenuItem</tt> and subclasses directly from <tt class=
"literal">AbstractButton</tt> class, so it shares much of the
functionality of the <tt class="literal">JButton</tt> class. You
can register an action listener with a menu for instance. The menu
item component makes more use of the super class's functionality,
the ability to set keyboard accelerator, or declare a mnemonic
key.</p>
<p>The pull down component is <tt class="literal">JMenu</tt> and
subclasses from <tt class="literal">JMenuItem</tt> class, which
might strike you as being strange object class design, until you
realise that there are such things as cascading menus - pull down
menus with menu items that invoke another pull down menu.
<tt class="literal">JMenuItem</tt>s can be added to a <tt class=
"literal">JMenu</tt> with a few convenience methods.</p>
<pre class="programlisting">
public JMenu extends JmenuItem implements MenuElement{
// Constructors
  public JMenu();
  public JMenu(String name);
  ...
// Methods
  public JMenuItem add(String s);
  public JMenuItem add(JMenuItem item);
  public JMenuItem add(Action action);
  ...
}
</pre>
<p>The <tt class="literal">JMenuItem</tt> method <tt class=
"literal">add(Action)</tt> is extremely useful. It allows us to
conveniently create a <tt class="literal">JMenuItem</tt> and
simultaneously register a binding <tt class="literal">Action</tt>.
If for example you disabled the action by calling <tt class=
"literal">setEnabled(false)</tt> then that change would be
propagated back to the <tt class="literal">JMenuItem</tt>. It could
then render itself as a greyed out button, and/or lock out any
mouse event behaviour. Additionally other Swing components,
<tt class="literal">JMenu</tt>, <tt class=
"literal">JPopupMenu</tt>, and <tt class="literal">JToolbar</tt>
directly allow <tt class="literal">Action</tt>s to be added to
them. They make use of the standard attributes of the <tt class=
"literal">Action</tt> interface like <tt class=
"literal">SHORT_DESCRIPTION</tt> and <tt class=
"literal">SMALL_ICON</tt> to automate the creation of tool tips,
and image icons. (Unfortunately for <tt class=
"literal">JButton</tt>, <tt class="literal">JToggleButton</tt>, and
<tt class="literal">JCheckBox</tt> do not provide this easy binding
of actions to components. Something that I think is missing from
the <tt class="literal">AbstractButton</tt> API framework!)</p>
<p>To add a menu bar and pulldown menus to our preferences
application we again have to modify the constructor.</p>
<pre class="programlisting">
public class PreferencesApp2 extends JFrame {
  ...
  public PreferencesApp2(String title){
    ...
// Create a second empty model for user configuration
    DefaultListModel configModel = new DefaultListModel();
// Create the menu bar and pulldown menu
    JMenuBar menubar = new JMenuBar();
    setJMenuBar(menubar);
    JMenu fileMenu = new JMenu(&quot;File&quot;);
    menubar.add(fileMenu);
    JMenuItem addMI = fileMenu.add(addAction);
    addMI.setMnemonic('A');
    JMenuItem removeMI = fileMenu.add(removeAction);
    removeMI.setMnemonic('R');
    fileMenu.addSeparator();
    JMenuItem quitMI = fileMenu.add(quitAction);
    quitMI.setMnemonic('Q');
    quitMI.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
    ...
  }
}
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e535" id=
"d0e535"></a>Conclusion</h2>
</div>
<p>This completes the second version of the application. You have
learn about inner workings of the top level component, in
particular the organisation of the root pane container. You have
learnt about <tt class="literal">Action</tt>s. You have learnt
about the list data model and how data models interact with the
Swing components. Finally you should understand how Swing menus,
menu items, and menu bars are put together for an application.</p>
<p>Download the entire article and finished example application
from <a href="http://www.xenonsoft.demon.co.uk/accu.html" target=
"_top">http://www.xenonsoft.demon.co.uk/accu.html</a>. Enjoy.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e548" id="d0e548"></a>Books and
References</h2>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="citetitle"><i class=
"citetitle">Java 2D Graphics</i></span> by Jonathan Knudsen (1
56592 484 3), O'Reilly</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="citetitle"><i class=
"citetitle">Java Swing</i></span> by Robert Eckstein, Marc Loy
&amp; Dave Wood (1 56592 455 X), O'Reilly</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="citetitle"><i class=
"citetitle">Swing</i></span> by Matthew Robinson and Pavel Vorobiev
(1 88477784 8), Manning</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://java.sun.com/products/jfc/" target=
"_top">http://java.sun.com/products/jfc/</a></span> Sun's product
home page of the JFC</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://java.sun.com/products/jfc/" target=
"_top">http://java.sun.com/products/jfc/</a></span> whitepaper.html
A white paper of the JFC philosophy</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://java.sun.com/products/jfc/tsc/" target=
"_top">http://java.sun.com/products/jfc/tsc/</a></span> The Swing
Connection Page</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://www.manning.com/Robinson/index.html" target=
"_top">http://www.manning.com/Robinson/index.html</a></span> Swing
Book</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://www.algonet.se/~set_lo/java/sbe/" target=
"_top">http://www.algonet.se/~set_lo/java/sbe/</a></span> On line
book Swing mirror in Sweden</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://www2.gol.com/users/tame/swing/%20examples/SwingExamples.html"
target="_top">http://www2.gol.com/users/tame/swing/
examples/SwingExamples.html</a></span> Tamemasu Nobuo's brilliant
Swing JFC examples with great screen shots
(intermediate/advanced)</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc"><a href=
"http://www.jguru.com/jguru/faq/faqpage%20.jsp?name=Swing" target=
"_top">http://www.jguru.com/jguru/faq/faqpage
.jsp?name=Swing</a></span> jGuru excellent frequently asked
questions on Swing</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
