JCardPane: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
Zeile 5: Zeile 5:
 
  * The main method shows an example.
 
  * The main method shows an example.
 
  */
 
  */
 
 
import java.awt.*;
 
import java.awt.*;
 
import java.awt.event.*;
 
import java.awt.event.*;
 
import java.beans.*;
 
import java.beans.*;
 
import java.util.*;
 
import java.util.*;
 +
import java.util.logging.*;
 
import javax.swing.*;
 
import javax.swing.*;
 
import javax.swing.event.*;
 
import javax.swing.event.*;
import javax.swing.plaf.TabbedPaneUI;
+
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
+
import javax.swing.plaf.basic.*;
  
 
public class JCardPane extends JComponent {
 
public class JCardPane extends JComponent {
Zeile 58: Zeile 58:
 
         pane.addChangeListener(new ChangeListener() {
 
         pane.addChangeListener(new ChangeListener() {
  
             public void stateChanged(ChangeEvent e) {
+
            @Override
 +
             public void stateChanged(final ChangeEvent e) {
 
                 if (nextAction != null) {
 
                 if (nextAction != null) {
 
                     nextAction.setEnabled(hasNext());
 
                     nextAction.setEnabled(hasNext());
Zeile 68: Zeile 69:
 
         });
 
         });
 
         setLayout(new BorderLayout());
 
         setLayout(new BorderLayout());
         add(pane);
+
         super.add(pane);
 
     }
 
     }
  
Zeile 165: Zeile 166:
 
         pane.setSelectedIndex(index);
 
         pane.setSelectedIndex(index);
 
         return index;
 
         return index;
 +
    }
 +
 +
    /**
 +
    * Flips to the specified card.
 +
    * If the card does not exist in the cardpane, it is added to it.
 +
    * @return the index of the specified card
 +
    */
 +
    public int add(final JComponent card) {
 +
        return show(card);
 +
    }
 +
 +
    /**
 +
    * Inserts the specified card at the sepcified index and
 +
    * flips to the specified card.
 +
    */
 +
    public void insertAt(JComponent card, int index){
 +
        pane.insertTab(null, null, card, null, index);
 +
        pane.setSelectedIndex(index);
 
     }
 
     }
  
Zeile 191: Zeile 210:
 
     * Adds a <code>ChangeListener</code> to this cardpane.
 
     * Adds a <code>ChangeListener</code> to this cardpane.
 
     */
 
     */
     public void addChangeListener(ChangeListener l) {
+
     public void addChangeListener(final ChangeListener l) {
 
         pane.addChangeListener(l);
 
         pane.addChangeListener(l);
 
     }
 
     }
Zeile 198: Zeile 217:
 
     * Removes a <code>ChangeListener</code> from this cardpane.
 
     * Removes a <code>ChangeListener</code> from this cardpane.
 
     */
 
     */
     public void removeChangeListener(ChangeListener l) {
+
     public void removeChangeListener(final ChangeListener l) {
 
         pane.removeChangeListener(l);
 
         pane.removeChangeListener(l);
 
     }
 
     }
Zeile 205: Zeile 224:
 
     * gets the action to be used for a "Next" button
 
     * gets the action to be used for a "Next" button
 
     */
 
     */
     public Action getNextAction(String name) {
+
     public Action getNextAction(final String name) {
 
         if (nextAction == null) {
 
         if (nextAction == null) {
 
             nextAction = new CardAction(name, true);
 
             nextAction = new CardAction(name, true);
             nextAction.putValue(Action.MNEMONIC_KEY, (int)name.charAt(0));
+
             nextAction.putValue(Action.MNEMONIC_KEY, (int) name.charAt(0));
 
             nextAction.setEnabled(hasNext());
 
             nextAction.setEnabled(hasNext());
 
         }
 
         }
Zeile 217: Zeile 236:
 
     * gets the action to be used for a "Previous" button
 
     * gets the action to be used for a "Previous" button
 
     */
 
     */
     public Action getPreviousAction(String name) {
+
     public Action getPreviousAction(final String name) {
 
         if (previousAction == null) {
 
         if (previousAction == null) {
 
             previousAction = new CardAction(name, false);
 
             previousAction = new CardAction(name, false);
             previousAction.putValue(Action.MNEMONIC_KEY, (int)name.charAt(0));
+
             previousAction.putValue(Action.MNEMONIC_KEY, (int) name.charAt(0));
 
             previousAction.setEnabled(hasPrevious());
 
             previousAction.setEnabled(hasPrevious());
 
         }
 
         }
Zeile 227: Zeile 246:
  
 
     /**
 
     /**
     *  
+
     *
 
     * retain: if true, the component focused within a card will remain focused
 
     * retain: if true, the component focused within a card will remain focused
 
     * each time it becomes visible, otherwise the first component of each card is focused
 
     * each time it becomes visible, otherwise the first component of each card is focused
 
     */
 
     */
     public void retainFocus(boolean retain) {
+
     public void retainFocus(final boolean retain) {
 
         int focusPolicy = TabFocusHandler.RESET_FOCUS;
 
         int focusPolicy = TabFocusHandler.RESET_FOCUS;
 
         if (retain) {
 
         if (retain) {
Zeile 248: Zeile 267:
 
         private boolean isNext;
 
         private boolean isNext;
  
         public CardAction(String text, boolean isNext) {
+
         CardAction(final String text, final boolean isNext) {
 
             super(text);
 
             super(text);
 
             this.isNext = isNext;
 
             this.isNext = isNext;
Zeile 254: Zeile 273:
 
         }
 
         }
  
         public void actionPerformed(ActionEvent e) {
+
        @Override
 +
         public void actionPerformed(final ActionEvent e) {
 
             if (isNext) {
 
             if (isNext) {
 
                 next();
 
                 next();
Zeile 271: Zeile 291:
 
     *  in which case the other policy will be in effect.
 
     *  in which case the other policy will be in effect.
 
     */
 
     */
     private class TabFocusHandler implements ChangeListener, PropertyChangeListener {
+
     private class TabFocusHandler {
  
 
         public final static int RESET_FOCUS = 0;
 
         public final static int RESET_FOCUS = 0;
 
         public final static int RETAIN_FOCUS = 1;
 
         public final static int RETAIN_FOCUS = 1;
         private HashMap<Component, Component> tabFocus = new HashMap<Component, Component>();
+
         private HashMap<Component, Component> tabFocus = new HashMap<Component, Component>(16);
 
         private HashSet<Component> exceptions;
 
         private HashSet<Component> exceptions;
 
         private JTabbedPane tabbedPane;
 
         private JTabbedPane tabbedPane;
 
         private int focusPolicy;
 
         private int focusPolicy;
 
         private final KeyboardFocusManager focusManager;
 
         private final KeyboardFocusManager focusManager;
 +
        private final ChangeListener changeListener;
 +
        private final PropertyChangeListener propertyChangeListener;
  
 
         /**
 
         /**
 
         *  Create with the default Retain Focus policy
 
         *  Create with the default Retain Focus policy
 
         */
 
         */
         public TabFocusHandler(JTabbedPane tabbedPane) {
+
         TabFocusHandler(final JTabbedPane tabbedPane) {
 
             this(tabbedPane, RETAIN_FOCUS);
 
             this(tabbedPane, RETAIN_FOCUS);
 
         }
 
         }
Zeile 291: Zeile 313:
 
         *  Create using the specified focus policy
 
         *  Create using the specified focus policy
 
         */
 
         */
         public TabFocusHandler(JTabbedPane tabbedPane, int focusPolicy) {
+
         TabFocusHandler(final JTabbedPane tabbedPane, final int focusPolicy) {
 
             if (focusPolicy != RESET_FOCUS && focusPolicy != RETAIN_FOCUS) {
 
             if (focusPolicy != RESET_FOCUS && focusPolicy != RETAIN_FOCUS) {
 
                 throw new IllegalArgumentException("Invalid focus policy");
 
                 throw new IllegalArgumentException("Invalid focus policy");
Zeile 298: Zeile 320:
 
             this.focusPolicy = focusPolicy;
 
             this.focusPolicy = focusPolicy;
 
             //  Add listeners to manage a tab change
 
             //  Add listeners to manage a tab change
             tabbedPane.addChangeListener(this);
+
            changeListener = new TabChangeListener();
 +
            propertyChangeListener = new TabPropertyChangeListener();
 +
             tabbedPane.addChangeListener(changeListener);
 
             focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
 
             focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
             focusManager.addPropertyChangeListener("permanentFocusOwner", this);
+
             focusManager.addPropertyChangeListener("permanentFocusOwner", propertyChangeListener);
 
         }
 
         }
  
 
         public void uninstall() {
 
         public void uninstall() {
             tabbedPane.removeChangeListener(this);
+
             tabbedPane.removeChangeListener(changeListener);
             focusManager.removePropertyChangeListener(this);
+
             focusManager.removePropertyChangeListener(propertyChangeListener);
 
         }
 
         }
  
Zeile 311: Zeile 335:
 
         *  Specify a tab with an exception to the focus policy rule
 
         *  Specify a tab with an exception to the focus policy rule
 
         */
 
         */
         public void addException(int index) {
+
         public void addException(final int index) {
 
             if (exceptions == null) {
 
             if (exceptions == null) {
                 exceptions = new HashSet<Component>();
+
                 exceptions = new HashSet<Component>(16);
 
             }
 
             }
 
             Component key = tabbedPane.getComponentAt(index);
 
             Component key = tabbedPane.getComponentAt(index);
Zeile 319: Zeile 343:
 
         }
 
         }
  
         /**
+
         private class TabPropertyChangeListener implements PropertyChangeListener {
        * Tab has changed. Focus on saved component for the given tab.
+
 
        * When there is no saved component, focus on the first component.
+
             TabPropertyChangeListener() {
        */
 
        public void stateChanged(ChangeEvent e) {
 
            Component key = tabbedPane.getComponentAt(tabbedPane.getSelectedIndex());
 
             if (key == null) {
 
                return;
 
 
             }
 
             }
             Component value = tabFocus.get(key);
+
 
            //  First time selecting this tab or focus policy is RESET_FOCUS
+
             /**
            if (value == null) {
+
            *  Track focus changes and update the current focus component
                 key.transferFocus();
+
            *  for the current tab
                 tabFocus.put(key, value);
+
            */
            } else //  Use the saved component for focusing
+
            @Override
            {
+
            public void propertyChange(final PropertyChangeEvent e) {
                 value.requestFocusInWindow();
+
                //  No need to track focus change
 +
                if (exceptions == null && focusPolicy == RESET_FOCUS) {
 +
                    return;
 +
                }
 +
                 Component key = tabbedPane.getComponentAt(tabbedPane.getSelectedIndex());
 +
                 if (exceptions != null) {
 +
                    if (focusPolicy == RESET_FOCUS && !exceptions.contains(key)) {
 +
                        return;
 +
                    }
 +
                    if (focusPolicy == RETAIN_FOCUS && exceptions.contains(key)) {
 +
                        return;
 +
                    }
 +
                }
 +
                 Component value = (Component) e.getNewValue();
 +
                if (value != null && SwingUtilities.isDescendingFrom(value, key)) {
 +
                    tabFocus.put(key, value);
 +
                }
 
             }
 
             }
 
         }
 
         }
  
         /**
+
         private class TabChangeListener implements ChangeListener {
        *  Track focus changes and update the current focus component
+
 
        *  for the current tab
+
             TabChangeListener() {
        */
 
        public void propertyChange(PropertyChangeEvent e) {
 
            //  No need to track focus change
 
             if (exceptions == null && focusPolicy == RESET_FOCUS) {
 
                return;
 
 
             }
 
             }
             //  Check for exceptions to the focus policy exist
+
 
             Component key = tabbedPane.getComponentAt(tabbedPane.getSelectedIndex());
+
             /**
            if (exceptions != null) {
+
            * Tab has changed. Focus on saved component for the given tab.
                 if (focusPolicy == RESET_FOCUS && !exceptions.contains(key)) {
+
            * When there is no saved component, focus on the first component.
 +
            */
 +
            @Override
 +
             public void stateChanged(final ChangeEvent e) {
 +
                Component key = tabbedPane.getComponentAt(tabbedPane.getSelectedIndex());
 +
                 if (key == null) {
 
                     return;
 
                     return;
 
                 }
 
                 }
                 if (focusPolicy == RETAIN_FOCUS && exceptions.contains(key)) {
+
                Component value = tabFocus.get(key);
                     return;
+
                //  First time selecting this tab or focus policy is RESET_FOCUS
 +
                 if (value == null) {
 +
                    key.transferFocus();
 +
                    tabFocus.put(key, value);
 +
                } else //  Use the saved component for focusing
 +
                {
 +
                     value.requestFocusInWindow();
 
                 }
 
                 }
            }
 
            // Track focus changes for the tab
 
            Component value = (Component) e.getNewValue();
 
            if (value != null && SwingUtilities.isDescendingFrom(value, key)) {
 
                tabFocus.put(key, value);
 
 
             }
 
             }
 
         }
 
         }
Zeile 367: Zeile 403:
  
 
     //for testing only:
 
     //for testing only:
     public static void main(final String[] args) {
+
     public static void main(final String... args) {
 
         try {
 
         try {
 
             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 
             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         } catch (Exception ex) {
+
         } catch (ClassNotFoundException ex) {
             ex.printStackTrace();
+
             Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
 +
        } catch (InstantiationException ex) {
 +
            Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
 +
        } catch (IllegalAccessException ex) {
 +
            Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
 +
        } catch (UnsupportedLookAndFeelException ex) {
 +
            Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
 
         }
 
         }
 
         Runnable gui = new Runnable() {
 
         Runnable gui = new Runnable() {
Zeile 385: Zeile 427:
 
                 class Card extends JPanel {
 
                 class Card extends JPanel {
  
                     public Card(final String name) {
+
                     Card(final String name) {
 
                         JTextField tf = new JTextField(20);
 
                         JTextField tf = new JTextField(20);
 
                         tf.setText(name);
 
                         tf.setText(name);

Version vom 16. März 2011, 11:25 Uhr

<code=java> /*

* JCardPane.java
* wraps a JTabbedPane, hiding the tabs.
* The main method shows an example.
*/

import java.awt.*; import java.awt.event.*; import java.beans.*; import java.util.*; import java.util.logging.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*;

public class JCardPane extends JComponent {

   private JTabbedPane pane;
   private CardAction nextAction;
   private CardAction previousAction;
   private TabFocusHandler tabFocusHandler;
   private TabbedPaneUI uiNoTabs = new BasicTabbedPaneUI() {
       @Override
       protected int calculateTabAreaHeight(int tabPlacement,
               int horizRunCount, int maxTabHeight) {
           return 0;
       }
       @Override
       protected Insets getContentBorderInsets(int tabPlacement) {
           return new Insets(0, 0, 0, 0);
       }
       @Override
       protected MouseListener createMouseListener() {
           return null;
       }
       @Override
       protected void installKeyboardActions() {
       }
       @Override
       protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
           return 0;
       }
   };
   /**
    * Creates an empty cardpane
    */
   public JCardPane() {
       pane = new JTabbedPane();
       tabFocusHandler = new TabFocusHandler(pane);
       hideTabs();
       pane.addChangeListener(new ChangeListener() {
           @Override
           public void stateChanged(final ChangeEvent e) {
               if (nextAction != null) {
                   nextAction.setEnabled(hasNext());
               }
               if (previousAction != null) {
                   previousAction.setEnabled(hasPrevious());
               }
           }
       });
       setLayout(new BorderLayout());
       super.add(pane);
   }
   /**
    * Flips to the first card of the cardpane.
    * @return 0 if this cardpane has a card
    * or -1 if this cardpane has no card
    */
   public int first() {
       return show(0);
   }
   /**
    * Flips to the last card of the cardpane.
    * @return 0 if this cardpane has a card
    * or -1 if this cardpane has no card
    */
   public int last() {
       return show(-1);
   }
   /**
    * Flips to the next card of the cardpane.
    * If the currently visible card is the last one,
    * this method flips to the first card of the cardpane.
    * @return the index of the card
    * or -1 if this cardpane has no card
    */
   public int next() {
       return show(pane.getSelectedIndex() + 1);
   }
   /**
    * Flips to the previous card of the cardpane.
    * If the currently visible card is the first one,
    * this method flips to the last card of the cardpane.
    * @return the index of the card
    * or -1 if this cardpane has no card
    */
   public int previous() {
       return show(pane.getSelectedIndex() - 1);
   }
   /**
    * Flips to the card at the specified index.
    * If the index is positive but does not exist,
    * this method flips to the first card of the cardpane.
    * If the index is negative,
    * this method flips to the last card of the cardpane.
    * @return the index of the card
    * or -1 if this cardpane has no card
    */
   public int show(final int index) {
       if (pane.getTabCount() == 0) {
           return -1;
       }
       if (index >= pane.getTabCount()) {
           pane.setSelectedIndex(0);
           return 0;
       }
       if (index < 0) {
           pane.setSelectedIndex(pane.getTabCount() - 1);
           return pane.getTabCount() - 1;
       }
       pane.setSelectedIndex(index);
       return index;
   }
   /**
    * Flips to the card with the specified name.
    * If the name does not exist, nothing happens.
    * @return the index of the card
    * or -1 if the name does not exist
    */
   public int show(final String name) {
       int index = pane.indexOfTab(name);
       if (index >= 0) {
           pane.setSelectedIndex(index);
       }
       return index;
   }
   /**
    * Flips to the specified card.
    * If the card does not exist in the cardpane, it is added to it.
    * @return the index of the specified card
    */
   public int show(final JComponent card) {
       int index = pane.indexOfComponent(card);
       if (index < 0) {
           index = pane.getTabCount();
           pane.addTab(card.getName(), card);
       }
       pane.setSelectedIndex(index);
       return index;
   }
   /**
    * Flips to the specified card.
    * If the card does not exist in the cardpane, it is added to it.
    * @return the index of the specified card
    */
   public int add(final JComponent card) {
       return show(card);
   }
   /**
    * Inserts the specified card at the sepcified index and
    * flips to the specified card.
    */
   public void insertAt(JComponent card, int index){
       pane.insertTab(null, null, card, null, index);
       pane.setSelectedIndex(index);
   }
   /**
    * @return true if there is a card after the visible one
    */
   public boolean hasNext() {
       return pane.getSelectedIndex() < pane.getComponentCount() - 1;
   }
   /**
    * @return true if there is a card before the visible one
    */
   public boolean hasPrevious() {
       return pane.getSelectedIndex() > 0;
   }
   /**
    * @return the visible card
    */
   public Component getCurrent() {
       return pane.getSelectedComponent();
   }
   /**
    * Adds a ChangeListener to this cardpane.
    */
   public void addChangeListener(final ChangeListener l) {
       pane.addChangeListener(l);
   }
   /**
    * Removes a ChangeListener from this cardpane.
    */
   public void removeChangeListener(final ChangeListener l) {
       pane.removeChangeListener(l);
   }
   /**
    * gets the action to be used for a "Next" button
    */
   public Action getNextAction(final String name) {
       if (nextAction == null) {
           nextAction = new CardAction(name, true);
           nextAction.putValue(Action.MNEMONIC_KEY, (int) name.charAt(0));
           nextAction.setEnabled(hasNext());
       }
       return nextAction;
   }
   /**
    * gets the action to be used for a "Previous" button
    */
   public Action getPreviousAction(final String name) {
       if (previousAction == null) {
           previousAction = new CardAction(name, false);
           previousAction.putValue(Action.MNEMONIC_KEY, (int) name.charAt(0));
           previousAction.setEnabled(hasPrevious());
       }
       return previousAction;
   }
   /**
    *
    * retain: if true, the component focused within a card will remain focused
    * each time it becomes visible, otherwise the first component of each card is focused
    */
   public void retainFocus(final boolean retain) {
       int focusPolicy = TabFocusHandler.RESET_FOCUS;
       if (retain) {
           focusPolicy = TabFocusHandler.RETAIN_FOCUS;
       }
       tabFocusHandler.uninstall();
       tabFocusHandler = new TabFocusHandler(pane, focusPolicy);
   }
   private void hideTabs() {
       pane.setUI(uiNoTabs);
   }
   private class CardAction extends AbstractAction {
       private boolean isNext;
       CardAction(final String text, final boolean isNext) {
           super(text);
           this.isNext = isNext;
           putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
       }
       @Override
       public void actionPerformed(final ActionEvent e) {
           if (isNext) {
               next();
           } else {
               previous();
           }
       }
   }
   /**
    *  Manage the focus when a new tab is selected. You can select a focus policy:
    *  a) Reset Focus - focus is reset to the first focusable component on the tab
    *  b) Retain Focus - focus returns to the last component with focus on the tab
    *
    *  In addition you add tabs that you want to exclude from the focus policy,
    *  in which case the other policy will be in effect.
    */
   private class TabFocusHandler {
       public final static int RESET_FOCUS = 0;
       public final static int RETAIN_FOCUS = 1;
       private HashMap<Component, Component> tabFocus = new HashMap<Component, Component>(16);
       private HashSet<Component> exceptions;
       private JTabbedPane tabbedPane;
       private int focusPolicy;
       private final KeyboardFocusManager focusManager;
       private final ChangeListener changeListener;
       private final PropertyChangeListener propertyChangeListener;
       /**
        *  Create with the default Retain Focus policy
        */
       TabFocusHandler(final JTabbedPane tabbedPane) {
           this(tabbedPane, RETAIN_FOCUS);
       }
       /**
        *  Create using the specified focus policy
        */
       TabFocusHandler(final JTabbedPane tabbedPane, final int focusPolicy) {
           if (focusPolicy != RESET_FOCUS && focusPolicy != RETAIN_FOCUS) {
               throw new IllegalArgumentException("Invalid focus policy");
           }
           this.tabbedPane = tabbedPane;
           this.focusPolicy = focusPolicy;
           //  Add listeners to manage a tab change
           changeListener = new TabChangeListener();
           propertyChangeListener = new TabPropertyChangeListener();
           tabbedPane.addChangeListener(changeListener);
           focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
           focusManager.addPropertyChangeListener("permanentFocusOwner", propertyChangeListener);
       }
       public void uninstall() {
           tabbedPane.removeChangeListener(changeListener);
           focusManager.removePropertyChangeListener(propertyChangeListener);
       }
       /**
        *  Specify a tab with an exception to the focus policy rule
        */
       public void addException(final int index) {
           if (exceptions == null) {
               exceptions = new HashSet<Component>(16);
           }
           Component key = tabbedPane.getComponentAt(index);
           exceptions.add(key);
       }
       private class TabPropertyChangeListener implements PropertyChangeListener {
           TabPropertyChangeListener() {
           }
           /**
            *  Track focus changes and update the current focus component
            *  for the current tab
            */
           @Override
           public void propertyChange(final PropertyChangeEvent e) {
               //  No need to track focus change
               if (exceptions == null && focusPolicy == RESET_FOCUS) {
                   return;
               }
               Component key = tabbedPane.getComponentAt(tabbedPane.getSelectedIndex());
               if (exceptions != null) {
                   if (focusPolicy == RESET_FOCUS && !exceptions.contains(key)) {
                       return;
                   }
                   if (focusPolicy == RETAIN_FOCUS && exceptions.contains(key)) {
                       return;
                   }
               }
               Component value = (Component) e.getNewValue();
               if (value != null && SwingUtilities.isDescendingFrom(value, key)) {
                   tabFocus.put(key, value);
               }
           }
       }
       private class TabChangeListener implements ChangeListener {
           TabChangeListener() {
           }
           /**
            * Tab has changed. Focus on saved component for the given tab.
            * When there is no saved component, focus on the first component.
            */
           @Override
           public void stateChanged(final ChangeEvent e) {
               Component key = tabbedPane.getComponentAt(tabbedPane.getSelectedIndex());
               if (key == null) {
                   return;
               }
               Component value = tabFocus.get(key);
               //  First time selecting this tab or focus policy is RESET_FOCUS
               if (value == null) {
                   key.transferFocus();
                   tabFocus.put(key, value);
               } else //  Use the saved component for focusing
               {
                   value.requestFocusInWindow();
               }
           }
       }
   }
   //for testing only:
   public static void main(final String... args) {
       try {
           UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
       } catch (ClassNotFoundException ex) {
           Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
       } catch (InstantiationException ex) {
           Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
       } catch (IllegalAccessException ex) {
           Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
       } catch (UnsupportedLookAndFeelException ex) {
           Logger.getLogger(JCardPane.class.getName()).log(Level.SEVERE, null, ex);
       }
       Runnable gui = new Runnable() {
           @Override
           public void run() {
               final JFrame f = new JFrame("JCardPane Demo");
               f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               f.setSize(400, 150);
               f.setLocationRelativeTo(null);
               final JCardPane cardPane = new JCardPane();
               f.add(cardPane, BorderLayout.CENTER);
               class Card extends JPanel {
                   Card(final String name) {
                       JTextField tf = new JTextField(20);
                       tf.setText(name);
                       add(tf);
                       tf = new JTextField(20);
                       tf.setText(name);
                       add(tf);
                       setName(name);
                   }
               }
               for (int i = 0; i < 5; i++) {
                   cardPane.show(new Card(String.valueOf(i + 1)));
               }
               cardPane.first();
               JPanel control = new JPanel();
               control.add(new JButton(cardPane.getPreviousAction("Previous")));
               control.add(new JButton(cardPane.getNextAction("Next")));
               f.add(control, BorderLayout.SOUTH);
               f.setVisible(true);
           }
       };
       //GUI must start on EventDispatchThread:
       SwingUtilities.invokeLater(gui);
   }

} </code=java>