简体   繁体   English

Java Swing FocusTraversalPolicy问题

[英]Java Swing FocusTraversalPolicy Issue

I'm currently having an issue with implementing a FocusTraversalPolicy . 我目前在实现FocusTraversalPolicy遇到问题。

I would like for the Tab / Shift+Tab keyboard shortcuts to allow for navigating top-bottom/left-right. 我想使用Tab / Shift+Tab键盘快捷键来浏览上下/左右。 This will allow for simpler navigation when filling in a form. 填写表格时,这将使导航更简单。

The policy should only impact all elements in the mainPanel of my JFrame . 该策略应仅影响JFramemainPanel的所有元素。

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 (eg main JFrame ): 然后,在我的视图的构造函数(例如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. 但是,当我尝试使用Tab键浏览元素时,没有任何变化,并且以前的策略仍然存在。 I've already tried going through the Java tutorial: link 我已经尝试过Java教程: 链接

Any help would be much appreciated. 任何帮助将非常感激。

I am not sure why you are even extending the FocusTraversalPolicy for your case while default FocusTraversalPolicy should do the job for you. 我不确定您为什么FocusTraversalPolicy为您的案例扩展FocusTraversalPolicy ,而默认FocusTraversalPolicy应该为您完成这项工作。

However, you need to set this.mainPanel.setFocusCycleRoot(true) : which sets whether this Container is the root of a focus traversal cycle. 但是,您需要设置this.mainPanel.setFocusCycleRoot(true) :它设置此Container是否为焦点遍历循环的根。 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. 正常遍历仅限于此Container,并且该Container的所有后代都不是下聚焦周期根的后代。

You can look into the ContainerOrderFocusTraversalPolicy : 您可以查看ContainerOrderFocusTraversalPolicy

  1. determines traversal order based on the order:returned by Container.getComponents() 根据以下顺序确定遍历顺序: Container.getComponents()返回
  2. From a particular focus cycle root, the policy makes a pre-order traversal of the Component hierarchy . 该策略从特定的关注周期根开始对Component层次结构进行预遍历。

It has a nice function: boolean accept(Component aComponent) : Determines whether a Component is an acceptable choice as the new focus owner. 它具有一个很好的功能: boolean accept(Component aComponent) :确定是否可以接受Component作为新的焦点所有者。 just override this function by extending this class, with your corresponding component list you don't want to be focused of the Container . 只需通过扩展此类来覆盖此函数,并使用您不希望关注Container相应组件列表即可。 No need to override all of the function and implement them. 无需覆盖所有功能并实现它们。

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();
            }
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM