Sunday, December 28, 2008

Controlling TabIndex in Java Swing

If you have used Visual Basic then you are familiar with TabIndex property. Well some one who moved to Java world recently would think "Where can i set the tab index in Swing applications ?", well the answer is "There is no place to do it."

In Swing tabindex is determined by the layout manager. Layout manager is what layout your GUI's components inside a container such as a JFrame.

So as Swing documentation explains if u want to take control over the tab order in swing you have to implement your own FocusTraversalPolicy. Let see how to do that.

if we check the FocusTraversalPolicy abstract class, there are few abstract methods namely getComponentAfter, getComponentBefore, getFirstComponent, getLastComponent, getDefaultComponent.

We can implement the above methods in such a way that our FocusTraversalPolicy will allow us to give the tab index for our components. So our next problem will be how are we going to record the order of tab index. Well we will be using a component collection which will contains the components where the collection's element order will represent the tab index. The user has to add his/her GUI components into the above collection in the order of tab index he/she needs. The below is part of my implementation.


private class IndexedFocusTraversalPolicy extends 
  FocusTraversalPolicy {

   private ArrayList<Component> components = 
      new ArrayList<Component>();

   public void addIndexedComponent(Component component) {
        components.add(component);
   }

   @Override
   public Component getComponentAfter(Container aContainer, 
               Component aComponent) {
        int atIndex = components.indexOf(aComponent);
        int nextIndex = (atIndex + 1) % components.size();
        return components.get(nextIndex);
   }

   @Override
   public Component getComponentBefore(Container aContainer,
         Component aComponent) {
        int atIndex = components.indexOf(aComponent);
        int nextIndex = (atIndex + components.size() - 1) %
                components.size();
        return components.get(nextIndex);
   }

   @Override
   public Component getFirstComponent(Container aContainer) {
        return components.get(0);
   }
}
Usage:
Put this code inside your JFrame constructor after you have initialized the GUI components.


IndexedFocusTraversalPolicy policy = new IndexedFocusTraversalPolicy();
policy.addIndexedComponent(jTextField1);
policy.addIndexedComponent(jTextField2);
policy.addIndexedComponent(jTextField3);
policy.addIndexedComponent(jTextField4);
policy.addIndexedComponent(jTextField5);
policy.addIndexedComponent(jTextField6);
setFocusTraversalPolicy(policy);


No matter what layout you use the above GUI's tab order will be as follows.
JtextField1 → jTextField2 → jTextField3 → jTextField4 → jTextField5 → jTextField6
So now you can control your GUI components tab order. :)

6 comments:

Ezra said...

In the below code,
---------------------------------
private ArrayListcomponent components = new
ArrayListcomponent();
---------------------------------

what is "component"?

Christian Enevoldsen said...
This comment has been removed by the author.
Abdulhafid Toshani said...

"what is "component"?"
change it to "Component" ,, worked for me

Thanx author ,, plain & simple.

GAP said...

Update the generic type case problem.

Yonanda Adhitama said...

Hallo, I sent you a question via google+. Could you please check it?
Thank you.

HENRY NOEL VARGAS MARTINEZ said...

The method setFocusTraversalPolicy(Main.IndexedFocusTraversalPolicy) is undefined for the type Main