Java FocusTraversalPolicy extend to create custom focus traversal policy

Introduction

Use Tab (or Shift-Tab) to navigate from component to component.

Control-Tab (or Control-Shift-Tab) allows you to break out of the JTable.

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;

public class Main extends JPanel implements ActionListener {
   static JFrame frame;
   JCheckBox togglePolicy;/*w ww  .  ja v  a 2  s . c om*/
   static MyOwnFocusTraversalPolicy newPolicy;

   public Main() {
      super(new BorderLayout());

      JTextField tf1 = new JTextField("Field 1");
      JTextField tf2 = new JTextField("A Bigger Field 2");
      JTextField tf3 = new JTextField("Field 3");
      JTextField tf4 = new JTextField("A Bigger Field 4");
      JTextField tf5 = new JTextField("Field 5");
      JTextField tf6 = new JTextField("A Bigger Field 6");
      JTable table = new JTable(4, 3);
      togglePolicy = new JCheckBox("Custom FocusTraversalPolicy");
      togglePolicy.setActionCommand("toggle");
      togglePolicy.addActionListener(this);
      togglePolicy.setFocusable(false); // Remove it from the focus cycle.
            
      JPanel leftTextPanel = new JPanel(new GridLayout(3, 2));
      leftTextPanel.add(tf1, BorderLayout.PAGE_START);
      leftTextPanel.add(tf3, BorderLayout.CENTER);
      leftTextPanel.add(tf5, BorderLayout.PAGE_END);
      leftTextPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 5));
      
      JPanel rightTextPanel = new JPanel(new GridLayout(3, 2));
      rightTextPanel.add(tf2, BorderLayout.PAGE_START);
      rightTextPanel.add(tf4, BorderLayout.CENTER);
      rightTextPanel.add(tf6, BorderLayout.PAGE_END);
      rightTextPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 5));

      JPanel tablePanel = new JPanel(new GridLayout(0, 1));
      tablePanel.add(table, BorderLayout.CENTER);
      tablePanel.setBorder(BorderFactory.createEtchedBorder());
      JPanel bottomPanel = new JPanel(new GridLayout(2, 1));
      bottomPanel.add(togglePolicy, BorderLayout.PAGE_START);

      add(leftTextPanel, BorderLayout.LINE_START);
      add(rightTextPanel, BorderLayout.CENTER);
      add(tablePanel, BorderLayout.LINE_END);
      add(bottomPanel, BorderLayout.PAGE_END);
      setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
      Vector<Component> order = new Vector<Component>(7);
      order.add(tf1);
      order.add(tf2);
      order.add(tf3);
      order.add(tf4);
      order.add(tf5);
      order.add(tf6);
      order.add(table);
      newPolicy = new MyOwnFocusTraversalPolicy(order);
   }
   public void actionPerformed(ActionEvent e) {
      if ("toggle".equals(e.getActionCommand())) {
         frame.setFocusTraversalPolicy(togglePolicy.isSelected() ? newPolicy : null);
      }
   }

   public static void main(String[] args) {
      frame = new JFrame("FocusTraversalDemo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JComponent newContentPane = new Main();
      newContentPane.setOpaque(true); // content panes must be opaque
      frame.setContentPane(newContentPane);

       frame.pack();
      frame.setVisible(true);
   }

}

class MyOwnFocusTraversalPolicy extends FocusTraversalPolicy {
   Vector<Component> order;

   public MyOwnFocusTraversalPolicy(Vector<Component> order) {
      this.order = new Vector<Component>(order.size());
      this.order.addAll(order);
   }

   public Component getComponentAfter(Container focusCycleRoot, Component aComponent) {
      int idx = (order.indexOf(aComponent) + 1) % order.size();
      return order.get(idx);
   }

   public Component getComponentBefore(Container focusCycleRoot, Component aComponent) {
      int idx = order.indexOf(aComponent) - 1;
      if (idx < 0) {
         idx = order.size() - 1;
      }
      return order.get(idx);
   }

   public Component getDefaultComponent(Container focusCycleRoot) {
      return order.get(0);
   }

   public Component getLastComponent(Container focusCycleRoot) {
      return order.lastElement();
   }

   public Component getFirstComponent(Container focusCycleRoot) {
      return order.get(0);
   }
}



PreviousNext

Related