SWING IN A NUTSHELL



 
Differences With AWT How Painting Works Swing and Threads
More Swing Features: JComponent Class JComponent Class
Top Level Containers: JFrame, JApplet, JDialog, JFrame Class JDialog Class
JOptionPane class JApplet Class JPanel Class
JScrollPane Class JSplitPane Class JTabbedPane Class
JToolBar Class JInternalFrame Class JLayeredPane Class
JRootPane Class Buttons JColorChooser Class
JComboBox Class JFileChooser Class JLabel Class
JList Class Menu JTable Class
Text Components Tool Tips  Swing-Continued

 
 

Differences Between  AWT and Swing

Even the simplest Swing components have capabilities far beyond what the AWT components offer:

     Swing lets you specify which look and feel your program's GUI uses. By contrast, AWT components always have
     the look and feel of the native platform.

     Another interesting feature is that Swing components with state use models to keep the state. A JSlider, for
     instance, uses a BoundedRangeModel object to hold its current value and range of legal values. Models are set
     up automatically, so you don't have to deal with them unless you want to take advantage of the power they can
     give you.

     If you're used to using AWT components, you need to be aware of a few gotchas when using Swing components:



Tip:    To view the containment hierarchy for any frame or dialog, click its border to select it, and then
          press Control-Shift-F1. A list of the containment hierarchy will be written to the standard output
          stream.


How Painting Works

    When a Swing GUI needs to paint itself -- whether for the first time, in response to becoming unhidden, or because it needs to reflect a change in the program's state -- it starts with the highest component that needs to be repainted and works its way down the containment hierarchy. This process is orchestrated by the AWT painting system, and made more efficient and smooth by the Swing repaint manager and double-buffering code.

     Swing components generally repaint themselves whenever necessary. When you invoke the setText method on a component, for example, the component should automatically repaint itself and, if appropriate, resize itself. If it doesn't, it's a bug. The workaround is to invoke the repaint method on the component to request that the component be scheduled for painting. If the component's size or position needs to change but doesn't do so  automatically, you should invoke revalidate upon the component before invoking repaint.

      Like event-handling code, painting code executes on the event-dispatching thread. While an event is being handled, no painting will occur. Similarly, if a painting operation takes a long time, no events will be handled during that time.

     For smoothness, Swing painting is double-buffered by default -- performed to an offscreen buffer and then flushed to the screen once finished. It might slightly help performance if you make a Swing component opaque, so  that the Swing painting system can know not to paint anything behind the component. To make a Swing component opaque, invoke setOpaque(true) on the component.



Swing and Threads

The Single-Thread Rule : Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.

Realized: A Swing component that's a top-level window is realized by having one of these methods invoked on it:
setVisible(true), show, or pack. Once a window is realized, all the components that it contains are realized.
Another way to realize a component is to add it to a container that's already realized.

Two JComponent methods are safe to call from any thread: repaint and revalidate.
These methods queue requests to be executed on the event-dispatching thread.
Also, it's always safe to call the addListenerTypeListener and removeListenerTypeListener methods.
The add/remove operations have no effect on an event dispatch that's under way.

The SwingUtilities class provides two methods to help you run code in the event-dispatching thread:

     invokeLater
          Requests that some code be executed in the event-dispatching thread. This method returns immediately,
          without waiting for the code to execute.

     invokeAndWait
          Acts like invokeLater, except that this method waits for the code to execute. As a rule, you should use
          invokeLater rather than this method.



More Swing Features:

JComponent : All non-top level swing components starting with J are subclass of JComponent class. It provides features like tooltip text, border, configurable L&F, Double Buffering etc.
Icons : Swing components such as JButton and JLabel can have images represented by Icon Objects.
Actions : If you want multiple objects to share state and data information during action event, use Action objects.
Pluggable Look and Feel : A Single program can have any one of several L&F. It can be chosen by the end user or set programmatically set.
Support Assistive Technologies: Swing API comes with in built support for Assistive Technologies.
Separate Data and State Models: All noncontainer Swing Components have a underlying model. JButton has a ButtonModel which stores information like - Keyboard Mnemonic, enabled state or not, selected, pressed and so.
Some Swing Component can have more than one underlying models. For example JList has ListModel which contains the List's contents and ListSelectionModel which contains information about its list selection.
Working with models directly is more efficient and faster.



JComponent Class

The JComponent class extends java.awt.Container class. There are some classes like Box.Filler which are not top-level container and that do not subclass JComponent.

Important methods include : setToolTipText, setBorder, registerKeyboardAction(specify a KeyStroke Object), putClientProperty, getClientProperty (properties for use by Layout Managers), setPreferredSize, setMinimumSize, setMaximumSize, setAlignmentX, setAlignmentY (setter methods: Component class provides getter methods), setOpaque, isOpaque etc



Top Level Containers: JFrame, JApplet, JDialog, JWindow

Each top-level container has a containment hierarchy of its own.

Top-Level container has a content-pane that contains all the visible components of the top-level container. It is an intermediate container that inherits from JComponent class with a BorderLayout layout Manager. getContentPane returns a Container object and not a JComponent object. Generally an opaque JComponent , such as JPanel, is constructed to contain all the visible components and set as the content pane with setContentPane.

In theory all top-level container can have a JMenuBar. But generally a JFrame or a JApplet has JMenuBar. Use setJMenuBar.

All top-level container has a RootPane that supports the content pane, menubar, Layered pane and Glass Pane.
It is used to intercept mouse click or paint over multiple components.

The layered pane directly contains the menu bar and content pane, and enables Z-ordering of other components you might add. The glass pane is often used to intercept input events occurring over the top-level container, and can also be used to paint over multiple components.



JFrame Class

     JFrame extends from java.awt.Frame.

     By default, when the user closes a frame onscreen, the frame is hidden. Although invisible, the frame still exists and
     the program can make it visible again. If you want different behavior, then you need to either register a window
     listener that handles window-closing events, or you need to specify default close behavior using the
     setDefaultCloseOperation method. You can even do both.

     The argument to setDefaultCloseOperation must be one of the following values, which are defined in the
     WindowConstants interface (which JFrame implements):

If the default close operation is to dispose the frame and also a window event listener is registered that checks if the frame is the last one and if so exits the application, then in such condition the window event listener is invoked first.

API: createRootPane, setRootPane, getRootPane, getGlassPane, setGlassPane, setLayeredPane, getLayeredPane, setContentPane, getContentPane, setJMenuBar, getJMenuBar, setDefaultCloseOperation etc



JDialog Class

     Extends the java.awt.Dialog class.

     Every dialog is dependent on a frame. When that frame is destroyed, so are its dependent dialogs. When the
     frame is iconified, its dependent dialogs disappear from the screen. When the frame is deiconified, its dependent
     dialogs return to the screen. The AWT automatically provides this behavior.

     A dialog can be modal. When a modal dialog is visible, it blocks user input to all other windows in the program.
     The dialogs that JOptionPane provides are modal. To create a non-modal dialog, you must use the JDialog
     class directly.

JOptionPane class

     It is a container that automatically creates a JDialog and put itself to the contentpane of the JDialog. It is Modal.

     JOptionPane's icon support lets you easily specify which icon the dialog displays. You can use a custom icon, no
     icon at all, or any one of four standard JOptionPane icons (question, information, warning, and error). Each look
     and feel has its own versions of the four standard icons.

     JOptionPane API:
 
Method Purpose
int showMessageDialog(Component, Object) 
int showMessageDialog(Component, Object, String, int) 
int showMessageDialog(Component, Object, String, int,
Icon) 
Show a one-button, modal dialog that gives the user some information. The arguments specify (in order) the parent   component, message, title, message type, and icon for the  dialog.
int showOptionDialog(Component, Object, String, int, int,Icon, Object[], Object Show a customized modal dialog. The arguments specify (in order) the parent component, message, title, option type, message type, icon, options, and initial value for the dialog.
int showConfirmDialog(Component, Object) 
int showConfirmDialog(Component, Object, String, int) 
int showConfirmDialog(Component, Object, String, int,
int) 
int showConfirmDialog(Component, Object, String, int,
int, Icon) 
A modal dialog that ask the user  a question. The arguments specify (in order) the parent   component, message, title, message type, and icon for the  dialog.
String showInputDialog(Object) 
String showInputDialog(Component, Object) 
String showInputDialog(Component, Object, String, int) 
String showInputDialog(Component, Object, String, int,
Icon, Object[], Object) 
Show a modal dialog that prompts the user for input. The single-argument version specifies just the message, with the parent component assumed to be null. The arguments for the other versions specify (in order) the parent component, message, title, message type, icon, options, and initial value for the dialog

Description of arguments in the above methods:

    Component parentComponent
          The first argument to each showXxxDialog method is always the parent component, which must be a
          frame, a component inside a frame, or null. If you specify a frame, then the dialog will appear over the
          center of the frame, and depend on that frame. If you specify a component inside a frame, then the dialog
          will appear over the center of that component, and depend on that component's frame. If you specify null,
          then the look and feel picks an appropriate position for the dialog -- generally the center of the screen, and
          the dialog doesn't depend on any visible frame.

          The JOptionPane constructors do not include this argument. Instead, you specify the parent frame when
          you create the JDialog that contains the JOptionPane, and you use the JDialog
          setLocationRelativeTo method to set the dialog's position.

     Object message
          This required argument specifies what the dialog should display in its main area. Generally, you specify a
          string, which results the dialog displaying a label with the specified text. You can split the message over
          several lines by putting newline (\n) characters inside the message string. For example:

               "Complete the sentence:\n \"Green eggs and...\""

     String title
          The title of the dialog.

     int optionType
          Specifies the set of buttons that appear at the bottom of the dialog. Choose from one of the following
          standard sets: DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION,
          OK_CANCEL_OPTION.

     int messageType
          This argument determines the icon displayed in the dialog. Choose from one of the following values:
          PLAIN_MESSAGE (no icon), ERROR_MESSAGE, INFORMATION_MESSAGE,
          WARNING_MESSAGE,   QUESTION_MESSAGE.

     Icon icon
          The icon to display in the dialog.

     Object[] options
          Further specifies the option buttons to appear at the buttom of the dialog. Generally, you specify an array of
          strings for the buttons. See Customizing Button Text in a Standard Dialog for more information.

     Object initialValue
          Specifies the default value to be selected.

Knowing User's Response:

The showMessageDialog, showConfirmDialog, and showOptionDialog methods return an integer indicating the user's choice. The values for this integer are YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION. Except for CLOSED_OPTION, each option corresponds to the button the user pressed. When CLOSED_OPTION is returned, it indicates that the user closed the dialog window explicitly, rather than by choosing a button inside the option pane.

Customized Dialog:

1. Create a JOptionPane like ... new JOptionPane(mesg,optionType, OptionType)
2. Create a JDialog
3. set the JOptionPane of step1 as the contentPane of the JDialog of step2
4. To override the default behaviour of a JOptionPane getting closed as the user chooses an option, register a PropertyChageListener to the JDialog. Get  propertyName and handle it according to your requirments.



JApplet Class
java.awt.Applet used getImage to get an Image object. JApplet uses ImageIcon to create an image icon from an image-URL, instead.

If the browser is Swing enabled an html file with <APPLET>tag can be used to run an applet. If the browser does not support swing, java plug-in must be used and the applet should be specified using <OBJECT> tag ot <EMBED> tag. There are tools that generates this new tags from <APPLET> tag.


Intermediate Swing Containers:

DeskTop Pane is a specialized Layered Pane intermediate container that is used to contain JInternalFrame.

JPanel Class
The Layout manager can be specified at instantiation time as an argument to the constructor or by using the setLayout method.



JScrollPane Class

You can change a scroll pane's client dynamically by calling the setViewportView method. Note that
JScrollPane has no corresponding getViewportView method, so you should cache the client object in a
variable if you need to refer to it later.
JScrollPane uses an instance of JViewPort to manage its visible region. It uses instances of JScrollBar to manage scrolling.

ScrollPane policy
The scroll bar policy of the horizontal and vertical scroll bars can be specified at creation time or set dynamically:

   JScrollPane(Component, vertPolicy, horiPolicy)
   JScrollPane(vertPolicy, horiPolicy)

   OR

  setHorizontalScrollBarPolicy(int)
  setVerticalScrollBarPolicy(int)

In above the int values can be one of the following constants defined in the ScrollPaneConstants Interface:
VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED, VERTICAL_SCROLLBAR_ALWAYS,  HORIZONTAL_SCROLLBAR_ALWAYS, VERTICAL_SCROLLBAR_NEVER,  HORIZONTAL_SCROLLBAR_NEVER

Custom Decorations
The area drawn by a scroll pane consists of up to nine parts: the center, four sides, and four corners. The center is
the only component that is always present in all scroll panes. Besides scroll bars, the sides can contain column and
row headers. A corner component is visible only if both sides that intersect at that corner contain visible
components.

API: setColumnHeaderView(Component), setRowHeaderView(Component), setCorner(JScrollPane.XXX_XXX_CORNER, Component)

Scroll-Savvy Client
To customize the way that a client component interacts with its scroll pane, you can make the component
implement the Scrollable interface. By implementing Scrollable, a client can specify both the size of the
viewport used to view it and the amount to scroll for clicks on the different controls on a scroll bar.

The Scrollable interface includes the following methods:

All these methods returns an integral value of pixels.

Lists, Tables, textComponents, and trees implements the scrollable interface.

Sizing the Scroll Pane
By default the size of a scroll pane is the preferred size of it nine components.
If the size of the client is fized then having a scroll pane is redundant. To get the scroll bars, in such as case, is to set the preferred size of the scroll pane or its container.
Scroll-savvy clients implements Scrollable interface and provides methods that the scroll pane uses to determine it scrolling behaviour. Scroll-savvy class like lists, tables provides methods the programmer can call to set the values returned by the methods of the Scrollable interface.

Dynamically Changing Client's Size
Step 1. Reset the preferred size of the client
Step 2. revalidate the client

API: setViewportView, setViewportBorder etc

Scrolling methods in other class : setVisibleRowCount (JList, JTree), setPreferredScrollableViewportSize (JTable) etc.



JSplitPane Class

JSplitPane([orientation],[boolean],[component1,component2])
orientation : JSplitPane.HORIZONTAL_SPLIT, JSplitPane.VERTICAL_SPLIT
boolean : Determines whether the component repaints as the user drags the split pane.

setOneTouchExpandable, setDividerSize, setDividerLocation, setOrientation, setLeftComponent, setRightComponent, setTopComponent, setBottomComponent



JTabbedPane Class

JTabbedPane([int]) : The int specfies constants from SwingConstants interface : TOP, BOTTOM, LEFT, RIGHT
addTab(TabLabelText, [Icon], component,[toolTipText]), setSelectedIndex(int) -- index starts from 0



JToolBar Class

It uses BoxLayout as its layout manager and hence can have its components call setAlignmentX, setAlignmentY etc.

API: JToolBar(), add(Component), add(Action), addSeparatot(), setFloatable(boolean) etc



JInternalFrame Class

The internal frame is implemented with platform-independent code and hence has more features than normal frames. It can specify the window decorations for resizing, iconifying, and maximizing. Internal frames cannot be root of a containment hierarchy. It does not generate windows event and generates Internal Frame events. Internal frame supports root pane and hence realizing GUI in internal frame is similar to that of normal frame.

Important rules while using internal frames:
- It is usually contained in a LayeredPane as JDeskTopPane.
- By default the internal frame has 0 size and must be set using pack, setSize or setBounds
- set the location in within its container using setLocation or setBounds
- to add components to an internal frame add it to the content pane of the internal frame
- to allow just outline drawing at the time of dragging use : internalframecontainer.setClientProperty("JDesktopPane.fragMode", "outline")

API: setJMenuBar, setDefaultCloseOperation, addInternalFrameListener, moveToFront, moveToBack etc



JLayeredPane Class

All containers with root pane supports a JLayeredPane.
There are 2 main classes of Layered Pane : JLayeredPane and its sublcass JDesktopPane.

A Layered Pane does not have default layout manager. This is because all existing managers lays out components as if all of them are in a single layer.

Depth: The higher the value higher the depth.
Position: The higher the value lower the depth with the same layer. If there are n components in a layer, the position ranges from 0 to n-1. -1 is same as n-1. For example when n=3 we have:

API: JLayeredPane(), add(Component,[depthasInteger],[positioninsamelayerasInt]), setLayer(Component, depthasInt, [positionasInt]), setPosition(Component, positionasInt), moveToFront(Component), moveToBack(Component) etc

If in add method depth is not specified it is assumed to be 0. If position is not specified then it is same n-1.
The setPosition and moveTo.. are methods for the same layer.



JRootPane Class

The JRootPane uses a JLayeredPane instance:

The description of each of this layers are shown below:
 
Layer Name Value Description
FRAME_CONTENT_LAYER new Integer(-30000)  This layer is used to position the frame's content pane and
menu bar. Most programs won't use this. The root pane
adds the menu bar and content pane to its layered pane at
this depth. 
DEFAULT_LAYER new Integer(0)  Most components go in this layer. If you don't specify a
component's depth, the layered pane puts it at this depth. 
PALETTE_LAYER  new Integer(100) This layer is useful for floating toolbars and palettes.
MODAL_LAYER new Integer(200) Modal internal-frame dialogs would belong in this layer.
POPUP_LAYER new Integer(300)  Popups go in this layer because they need to appear above
just about everything. 
DRAG_LAYER  new Integer(400)  Move a component to this layer when dragging. Return the
component to its regular layer when dropped. 



Buttons

All button classes are subclasses of AbstractButton. Different buttons include : JButton, JCheckBox, JRadioButton, JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem, JToggleButton.
Generally buttons listen to Action Events while CheckBox listens to Item Events. But selecting a CheckBox also genarates an ActionEvent.
Swing Buttons can have both text labels as well as image.

A button can be set as the default button of a top level container by calling the setDefaultButton method on the root pane of the top-level container. The  text label of a JButton can be specified by using HTML.

JCheckBox
JCheckBox chkBox = new JCheckBox("TOP or BOTTOM", imageIcon);
chkBox.setMnemonic(KeyEvent.VK_C);
chkBox.setSelected(true);
chkBox.addItemListener(....)

JRadioButton
JRadioButton radBtn1 = new JRadioButton("radiobtn1", imageIcon1);
radbtn1.setMnemonic(KeyEvent.VK_R);
radBtn1.setSelected(true);
radBtn1.addActionListener(...)
JRadioButton radBtn2 = new JRadioButton("radiobtn2", imageIcon2);
radbtn2.setMnemonic(KeyEvent.VK_S);
radBtn2.addActionListener(...)

ButtonGroup rg = ButtonGroup()
rg.add(radBtn1);
rg.add(radBtn2);

API: setText, setIcon, setDisabledIcon, setPressedIcon, setSelectedIcon, setHorizontalAlignmnet, setVerticalAlignment, setHorizontalTextPosition, setVerticalTextPosition, doClick etc



JColorChooser Class
The Color Chooser contains 2 parts: a tabbed pane and a preview panel. The 3 tabs in the tabbed pane select Chooser Panels. The preview panel below the tabbed pane displays the selected color.

The ColorChooser implements the ColorSelectionModel to which we can register a Change Event Listener in which we can get the selected color and do the needful:

tcc.getSelectionModel().addChangeListener(
              new ChangeListener() {
                  public void stateChanged(ChangeEvent e) {
                      Color newColor = tcc.getColor();
                      banner.setForeground(newColor);
                  }
              }
   );

The chosen color is used to set the forground color of a label called "banner".



JComboBox Class
There are 2 main types of JComboBox: uneditable (default) and editable.
JComboBox generates action and Item events.
JComboBox does not allow multiple selection.

The default renderer for JComboBox displays strings and icon. If objects other than strings and icon are to be displayed then a custom renderer must be set. The custom renderer must implement the ListCellRenderer interface. This works for JList also.
If the JComboBox is an editable one then a custom editor which implements ComboBoxEditor can be used.

API: JComboBox(Object[]), JComboBox(Vector), addItem(Object), addItemAt(Object,int), getItemAt(int), getSelectedItem(), removeAllItems(), removeItemAt(int), getItemCount(), setEditable(boolean), setRenderer(ListCellRenderer) etc



JFileChooser Class
It allows choosing a file for opening or saving.

Opening a file
JFileChooser fc = new JFileChooser("someDirectory");  // "someDirectory" could be replaced by a File Object
int sel = fc.showOpenDialog(componentObj);
if (sel == JFileChooser.APPROVE_ACTION) {
    File selFile = fc.getSelectedFile();
   ...
} else {
  // sel == JFileChooser.CANCEL_OPTION
 ....
}

API: setCurrentDirectory, showSaveDialog, etc



JLabel Class
Represents text and/or icon that do not repsond to user input.
Supports html for text.

Constructor : JLabel([textString],[icon],[horizonAlign]) : Here horizontal alignment is any of the SwingConstants - LEFT, CENTER, RIGHT, LEADING, TRAILING.

other API: setText, setIcon, setVerticalAlignment, setHorizontalAlignment, setVerticalTextPosition, setHorizontalTextPosition, setLabelFor(component) etc



JList Class

Constructor :

JList(Vector) , JList(Object[]) : creates a list whose listmodel is immutable and hence new elements cannot be added, removed or replaced.
JList(ListModel) : allows to create a list with the specified ListModel which can be Immutable, say DefaultListModel. Such a list can have its element removed, replaced or added after creation. Another way of changing the model is by calling the setModel() method.

SelectionMode:

List uses an instance of ListSelectionModel to manage selection. By default the selection mode is MULTIPLE_INTERVAL_SELECTION. Other selection mode can be set by using setSelectioMode method. The argumements are constants from ListSelectionModel : SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION.

List generates ListSelectionEvent which are handled by ListSelectionListener that defines the ValueChanged method.
The ListSelectionListener is added to the list instance.

Adding, Removing and Inserting elements:

Add and insert elements to the list model using addElement and insertElementAt methods.
Remove elements from the list instance using the remove(index) method.

Custom Renderer:

Same as that of custom renderer in Combo box.

API: setSelectedIndex, setSelectedIndices, getSelectedIndex, getSelectedIndices, getMinSelectedIndex, getMaxSelectedIndex, getSelectedValue, getSelectedValues, getFirstVisibleIndex, getLastVisibleIndex, getVisibleRowCount, setVisibleRowCVount etc



Menu

Here is a picture of the inheritance hierarchy for the menu-related classes:

As the figure shows, menu items (including menus) are simply buttons. You might be wondering how a menu, if it's
only a button, shows its menu items. The answer is that when a menu is activated, it automatically brings up a
popup menu that displays the menu items.

Enabling Keyboard Operation:

     Menus support two kinds of keyboard alternatives: mnemonics and accelerators. Mnemonics offer a way to use
     the keyboard to navigate the menu hierarchy, increasing the accessibility of programs. Accelerators, on the other
     hand, offer keyboard shortcuts to bypass navigating the menu hierarchy. Mnemonics are for all users; accelerators
     are for power users.

     You can specify a mnemonic either when constructing the menu item or with the setMnemonic method. To
     specify an accelerator, use the setAccelerator method. Here are examples of setting mnemonics and
     accelerators:

          //Setting the mnemonic when constructing a menu item:
          menuItem = new JMenuItem("A text-only menu item",
                                   KeyEvent.VK_T);

          //Setting the mnemonic after creation time:
          menuItem.setMnemonic(KeyEvent.VK_T);

          //Setting the accelerator:
          menuItem.setAccelerator(KeyStroke.getKeyStroke(
                  KeyEvent.VK_T, ActionEvent.ALT_MASK));

Popup Menu:
     To bring up a popup menu ( JPopupMenu), you must register a mouse listener on each component that the
     popup menu should be associated with. The mouse listener must detect user requests that the popup menu be
     brought up.

    The mouse listener brings up the popup menu by invoking the show method on the appropriate JPopupMenu
     instance. Example code:

          //...where instance variables are declared:
          JPopupMenu popup;

              //...where the GUI is constructed:
              //Create the popup menu.
              popup = new JPopupMenu();
              menuItem = new JMenuItem("A popup menu item");
              menuItem.addActionListener(this);
              popup.add(menuItem);
              menuItem = new JMenuItem("Another popup menu item");
              menuItem.addActionListener(this);
              popup.add(menuItem);

              //Add listener to components that can bring up popup menus.
              MouseListener popupListener = new PopupListener();
              output.addMouseListener(popupListener);
              menuBar.addMouseListener(popupListener);
          ...
          class PopupListener extends MouseAdapter {
              public void mousePressed(MouseEvent e) {
                  maybeShowPopup(e);
              }

              public void mouseReleased(MouseEvent e) {
                  maybeShowPopup(e);
              }

              private void maybeShowPopup(MouseEvent e) {
                  if (e.isPopupTrigger()) {
                      popup.show(e.getComponent(),
                                 e.getX(), e.getY());
                  }
              }
          }

Customizing Menu Layout:
The Menubar uses Horizontal BoxLayout and hence menus on it can be customized by adding Box.createHorizontalGlue to it, so that some menus are to the rightmost portion of the menubar.



JTable Class

Creating Simple Tables:

JTable(Object[][] rowData, Object[] columnNames)
JTable(vector rowData, vector columnNames)

The  contructors create tables with the default table model and has the following restrictions:
* All cells are editable
* All columns are of the same type - String
* Row data cannot be modified/added/removed dynamically

Adding a table to a container:

Tables are generally added to a JScrollPane in which the scroll pane automatically adds the table header:
          JScrollPane scrollPane = new JScrollPane(table);
          table.setPreferredScrollableViewportSize(new Dimension(500, 70));

If some other container is used the table header should be explicitly set:
          container.setLayout(new BorderLayout());
          container.add(table.getTableHeader(), BorderLayout.NORTH);
          container.add(table, BorderLayout.CENTER);

Setting the Initial width of a column:

 TableColumn tc = table.getColumnModel().getColumn(2);
 tc.setPreferredWidth(100);

The minimum, maximum and current width of a column can also be set.
The resize behaviour of columns can be set by using the method setAutoResizeMode(JTable.constants).  The constants
include : AUTO_RESIZE_SUBSEQUENT_COLUMNS , AUTO_RESIZE_NEXT_COLUMN,
AUTO_RESIZE_OFF.

Setting the Selection Model:

By default the selection model is multiple row selection over multiple intervals. Cells or columns cannot be individually
selected.
The selection mode can be set as :
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)

A listSelctionListener can be registered to the ListSelectionmodel of the table as in List:

ListSelectionModel lsm = table.getSelectionModel();
lsm.addListSelectionListener(new ListSelectionListener() {
     public void valueChanged(ListSelectionEvent e) {
        ListSelectionModel m = (ListSelctionModel) e.getSource();

        if (m.isSelectionEmpty()) {
         ....
      } else {
          int selIndx = m.getMinSelectedIndex();
    }
 }
});
 

A sample customized Table Model:

Generally table models are subclasses of AbstractTableModel.

Tables created using this table model :
* Stores it own row data
* The column type is determined by the class of the column
* Allows editing to all coumns 2 and greater

        class MyTableModel extends AbstractTableModel {
              final String[] columnNames = ...//same as before...
              final Object[][] data = ...//same as before...

              public int getColumnCount() {
                  return columnNames.length;
              }

              public int getRowCount() {
                  return data.length;
              }

              public String getColumnName(int col) {
                  return columnNames[col];
              }

              public Object getValueAt(int row, int col) {
                  return data[row][col];
              }

              public Class getColumnClass(int c) {
                  return getValueAt(0, c).getClass();
              }

              /*
               * Don't need to implement this method unless your table's
               * editable.
               */
              public boolean isCellEditable(int row, int col) {
                  //Note that the data/cell address is constant,
                  //no matter where the cell appears onscreen.
                  if (col < 2) {
                      return false;
                  } else {
                      return true;
                  }
              }

              /*
               * Don't need to implement this method unless your table's
               * data can change.
               */
              public void setValueAt(Object value, int row, int col) {
                  ...//debugging code not shown...
                  ...//ugly class cast code for Integers not shown...
                  data[row][col] = value;
                  fireTableCellUpdated(row, col);
                  ...//debugging code not shown...
              }
              ...

Table model events for Data Changes:

The AbstractTableModel defines many methods that fires table model events that are always recognized by the table.
This includes : fireTableCellUpdated, fireTableChanged, fireTableDataChanged, fireTableRowsDeleted,
fireTableRowsInserted,fireTableRowsUpdated, and fireTableStructureChanged.

If the default table model is used we need to register a TableModelListener to the table model to check edits on cells:

public class SimpleTableDemo ... implements TableModelListener {
              ...
              public SimpleTableDemo() {
                  ...
                  model = table.getModel();
                  model.addTableModelListener(this);
                  ...
              }

              public void tableChanged(TableModelEvent e) {
                  ...
                  int row = e.getFirstRow();
                  int column = e.getColumn();
                  String columnName = model.getColumnName(column);
                  Object data = model.getValueAt(row, column);

                  ...// Do something with the data...
              }
              ...
          }

Cell Renderer and Cell editors:

A single Cell Renderer is used to display cell values in all columns that have the same data type.
Cell editor takes over the cell when editing starts.

For example all number column cells used a single instance of right-aligned JLabel as a Cell Renderer. And it uses an
instance of a right-aligned JTextField as a cell editor.

Algorithm for choosing renderer and editor:
Both renderer and editor uses the following algorithm:

* check to see if a renderer is specified for that particular column. if so use it.
* if no renderer is specified call getClassName() method on the model
* chose from the following default table the renderer. (this list can be changed programmatically):

               Boolean -- rendered with a check box.
               Number -- rendered by a right-aligned label.
               ImageIcon -- rendered by a centered label.
               Object -- rendered by a label that displays the object's string value.

Validating User-Entered Text:

The cell editor can be used to validate user entry as the user enter them (change validation) or after the user ends the
enrty (action validation). The following example sets up a change validated text field editor for all columns whose data
type is Integer:

          final WholeNumberField integerField = new WholeNumberField(0, 5);
          integerField.setHorizontalAlignment(WholeNumberField.RIGHT);

          DefaultCellEditor integerEditor =
              new DefaultCellEditor(integerField) {
                  //Override DefaultCellEditor's getCellEditorValue method
                  //to return an Integer, not a String:
                  public Object getCellEditorValue() {
                      return new Integer(integerField.getValue());
                  }
              };
          table.setDefaultEditor(Integer.class, integerEditor);

In above the class WholeNumberField is custom subclass of JTextField that allows only digits to be entered.
 

Setting a Combo Box as a cell editor:

TableColumn tc = table.getColumnModel().getColumn(2);
tc.setCellEditor(new DefaultCellEditor(aComboBoxInstance));

The DefaultCellEditor, which implements the TableCellEditor, allows only JComboBox, JCheckBox and JTextField to
be specified. If some other type of classes need to be sapecified as the editor then you need to create a subclass of the
desired editor component and the subclass must implement the TableCellEditor interface.

Custom Renderer:

Creating a custom renderer is as simple as subclassing the desired component and implementing the TableCellRenderer
interface. The new renderer can be set as:
table.setDefaultRenderer(class, new customCellRenderer());

Cell specific renderers can also be provided.

Sorting and Manipulating tables:
Specialized tables or data manipulators can be used besides the data model for data manipulation such as sorting.
(The tutorial provides TableMap and TableSorter classes).



Text Components

The following diagram shows the hierarchy diagram of the text components:

Plain Text areas can display/contain single font unformatted data. Styled Text Areas allows text of more than one font. JTextEditorPane allows text to be loaded from a preexisting file by using an URL.

Basic TextComponents:

JTextField:
JTextField textField = new JTextField(10);
textField.setActionCommand(textFieldString);
textField.addActionListener(this);
String str = textField.getText()

JPasswordField:
JPasswordField passwordField = new JPasswordField(10);
passwordField.setEchoChar('#');
passwordField.setActionCommand(passwordFieldString);
passwordField.addActionListener(this);
char[] pass = passwordField.getPassword();

Stores the field values as an array of characters and not as a string.

JTextArea:
JTextArea textArea = new JTextArea("...sone text...");
textArea.setFont(new Font("Serif", Font.ITALIC, 16));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);

JEditorPane:
JEditorPane editorPane = new JEditorPane();
editorPane.setEditable(false);
 ...//create a URL object for the TextSamplerDemoHelp.html file...
try {
              editorPane.setPage(url);
     } catch (IOException e) {
              System.err.println("Attempted to read a bad URL: " + url);
    }

Basic Editor Pane supports : Plain Text, RTF, and HTML.

JTextPane:
Can specify various different paragraph and character format for different texts in the same text pane.

JTextComponent : Concepts

JTextComponent provides to all components the following:
* A model called the document  to handle the component's content
* View
* Editor kit, that can read and write text and implements editing capabilities with Actions
* Customizable keymaps and key bindings
* Infinite undo and redo
* Pluggable Caret and Caret change Listener

Document:
Document is the data model of the text component and it contains the data of the component. The document hierarchy is:

                         AbstractDocument
                     (implements Document)
                                 |
                  +--------+-------+
                  |                           |
            PlainDocument         DefaultStyledDocument
                                            (implements StyledDocument)
                                                     |
                                                    +
                                                     |
                                         HTMLDocument
PlainDocument is the default for textfields, text areas ans text editor. DefaultStyledDocument is the default document for text pane.

Documents can be customized ,say to limit the number of characters it can contain. Important methods in customozation includes : insertString, remove etc. setDocument from JTextComponent can be used to set te document.
A documentListener can listen to insert, remove or change in text format. Do not try to update the text of a component from a document listener.

Editor Kits:
Supports editing commands such as copy, paste, cut, insert etc by using Action object. Through its read and write methods, editor kit knows how to read and write text of a particular format.
All action commands can be obtained by using the getActions method of the JTextComponenet.The Actions can be associated with a GUI component and/or KeyStroke.
Important editor kits include: DefaultEditorLit, StyledEditotKit, HTMLEditorKit, RTFEditorKit.

KeyMaps:
Every text component has one or more keymaps-- each of which is an instance of the Keymap class. A
keymap contains a collection of name-value pairs where the name is a KeyStroke and the value is an
Action. Each pair binds the keystroke to the action such that when the user types the keystroke, the
action occurs.
All text components has a default Keymap. This default can be modified or enhanced.

Undo and Redo:
Two main steps are invloved:

1. Remembering Undoable edits
  --> Create an instance of the UndoManager, say undo
  --> Register an UndoableEditListener to the TextComponent. The UndoableEditListener Remembers the edit and updates the GUI components that control the undo and redo:

     protected class MyUndoableEditListener  implements UndoableEditListener  {
              public void undoableEditHappened(UndoableEditEvent e) {
                  //Remember the edit and update the menus
                  undo.addEdit(e.getEdit());
                  undoAction.updateUndoState();
                  redoAction.updateRedoState();
              }
          }

In above, undoAction and redoAction are Action objects (subclass of AbstractAction) that corresponds to the GUI components for undo and redo.

2. Implementing the Undo and Redo commands for the GUI components:
The code  for the UndoAction, ( which is set as the action of the Redo MenuItem of a Menu), may look like:

     public void actionPerformed(ActionEvent e) {
              try {
                  undo.undo();
              } catch (CannotUndoException ex) {
                  System.out.println("Unable to undo: " + ex);
                  ex.printStackTrace();
              }
              updateUndoState();
              redoAction.updateRedoState();
          }
The code for RedoAction is analogous to that of the UndoAction.

Caret and Selection Listener:
A caret listener can be added to a text component to listen to caret position and selection changes.
 

Using Text Fields:
To change-validate a textfield use a customized document and not a document listener. This is because by the time the document listener is called it is too late and the change has already been done.

Action validation is done in the action listener.

Document Listener:
Do not use documentListener for field validation but to listen to , and not interfere, with changes to the document's contents. DocumentListener methods includes: insertUpdate, removeUpdate, changeUpdate etc



Tool Tips

JComponent.setToolTipText("Hi this is  a tool tip text");
If you are to set tool tip text to tabs of a tapped pane, specify it in the addTab method.