Java Swing FocusTraversalPolicy Issue

允我心安 提交于 2019-12-23 00:51:43

问题


I'm currently having an issue with implementing a FocusTraversalPolicy.

I would like for the Tab/Shift+Tab keyboard shortcuts to allow for navigating top-bottom/left-right. This will allow for simpler navigation when filling in a form.

The policy should only impact all elements in the mainPanel of my JFrame.

I have implemented the policy using the following class:

public class DefaultViewFocusTraversalPolicy
        extends FocusTraversalPolicy
{
   ArrayList<Component> order;

   public DefaultViewFocusTraversalPolicy(ArrayList<Component> order)
   {
      this.order = order;
   }

   @Override
   public Component getComponentAfter(Container aContainer, Component aComponent)
   {
      int index = (order.indexOf(aComponent) + 1) % order.size();
      Component after = order.get(index);
      while (index < order.size() && !(after.isEnabled() && after.isVisible()))
      {
         index++;
         after = order.get(index);
      }
      return after;
   }

   @Override
   public Component getComponentBefore(Container aContainer, Component aComponent)
   {
      int index = order.indexOf(aComponent) - 1;
      if (index < 0)
      {
         index = order.size() - 1;
      }
      Component before = order.get(index);
      while (index >= 0 && !(before.isEnabled() && before.isVisible()))
      {
         index--;
         before = order.get(index);
      }
      return before;
   }

   @Override
   public Component getFirstComponent(Container aContainer)
   {
      int index = 0;
      Component first = order.get(index);
      while (index < order.size() && !(first.isEnabled() && first.isVisible()))
      {
         index++;
         first = order.get(index);
      }
      return first;
   }

   @Override
   public Component getLastComponent(Container aContainer)
   {
      int index = order.size() - 1;
      Component last = order.get(index);
      while (index >= 0 && !(last.isEnabled() && last.isVisible()))
      {
         index--;
         last = order.get(index);
      }
      return last;
   }

   @Override
   public Component getDefaultComponent(Container aContainer)
   {
      return getFirstComponent(aContainer);
   }
}

I then instantiate the class with the following inside the constructor of my view (e.g. main JFrame):

ArrayList<Component> order = new ArrayList<>();
order.add(this.ecmID);
order.add(this.modeID);
// ...
DefaultViewFocusTraversalPolicy policy =
        new DefaultViewFocusTraversalPolicy(order);
this.mainPanel.setFocusTraversalPolicy(policy);

However, when I try to Tab through the elements, nothing has changed and the previous policy is still in place. I've already tried going through the Java tutorial: link

Any help would be much appreciated.


回答1:


I am not sure why you are even extending the FocusTraversalPolicy for your case while default FocusTraversalPolicy should do the job for you.

However, you need to set this.mainPanel.setFocusCycleRoot(true): which sets whether this Container is the root of a focus traversal cycle. Once focus enters a traversal cycle, typically it cannot leave it via focus traversal unless one of the up- or down-cycle keys is pressed. Normal traversal is limited to this Container, and all of this Container's descendants that are not descendants of inferior focus cycle roots.

You can look into the ContainerOrderFocusTraversalPolicy:

  1. determines traversal order based on the order:returned by Container.getComponents()
  2. From a particular focus cycle root, the policy makes a pre-order traversal of the Component hierarchy .

It has a nice function: boolean accept(Component aComponent): Determines whether a Component is an acceptable choice as the new focus owner. just override this function by extending this class, with your corresponding component list you don't want to be focused of the Container. No need to override all of the function and implement them.




回答2:


ArrayList<Component> order = new ArrayList<>();

I think that you looking for

import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.awt.GridLayout;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Testing {

    private static final long serialVersionUID = 1L;
    private Component[] focusList;
    private int focusNumber = 0;
    private JFrame frame;

    public Testing() {
        JTextField tf1 = new JTextField(5);
        tf1.setName("tf1");
        JTextField tf2 = new JTextField(5);
        tf2.setName("tf2");
        JTextField tf3 = new JTextField(5);
        tf3.setName("tf3");
        JButton b1 = new JButton("B1");
        b1.setName("b1");
        JButton b2 = new JButton("B2");
        b2.setName("b2");
        tf2.setEnabled(false);
        focusList = new Component[]{tf1, b1, tf2, b2, tf3};
        JPanel panel = new JPanel(new GridLayout(5, 1));
        panel.add(tf1);
        panel.add(b1);
        panel.add(tf2);
        panel.add(b2);
        panel.add(tf3);
        frame = new JFrame();
        frame.setFocusTraversalPolicy(new MyFocusTraversalPolicy());
        frame.add(panel);
        frame.pack();
        frame.setLocation(150, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
            @Override
            public boolean dispatchKeyEvent(KeyEvent ke) {
                if (ke.getID() == KeyEvent.KEY_PRESSED) {
                    if (ke.getKeyCode() == KeyEvent.VK_TAB) {
                        Component comp = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
                        System.out.println(comp.getName());
                        if (comp.isEnabled() == false) {
                            if (ke.isShiftDown()) {
                                KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
                            } else {
                                KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
                            }
                        }
                    }
                }
                return false;
            }
        });
    }

    private class MyFocusTraversalPolicy extends FocusTraversalPolicy {

        @Override
        public Component getComponentAfter(Container focusCycleRoot, Component aComponent) {
            focusNumber = (focusNumber + 1) % focusList.length;
            return focusList[focusNumber];
        }

        @Override
        public Component getComponentBefore(Container focusCycleRoot, Component aComponent) {
            focusNumber = (focusList.length + focusNumber - 1) % focusList.length;
            return focusList[focusNumber];
        }

        @Override
        public Component getDefaultComponent(Container focusCycleRoot) {
            return focusList[0];
        }

        @Override
        public Component getLastComponent(Container focusCycleRoot) {
            return focusList[focusList.length - 1];
        }

        @Override
        public Component getFirstComponent(Container focusCycleRoot) {
            return focusList[0];
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Testing testing = new Testing();
            }
        });
    }
}


来源:https://stackoverflow.com/questions/20200589/java-swing-focustraversalpolicy-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!