Думаю, вы ищете Подсистему Фокуса . Он отвечает за порядок, в котором компоненты получают фокус при нажатии клавиши обхода фокуса. Например, вы можете определить порядок компонентов для получения фокуса, а также добавить проверку для передачи фокуса только включенным компонентам. Что вы также, кажется, хотите сделать, так это добавить клавишу ENTER в качестве клавиши обхода фокуса (ie при ее нажатии фокус будет перенесен на другой компонент - в соответствии с текущей политикой обхода фокуса) . Все это можно сделать через подсистему фокуса.
Кажется, что следующий код делает то, что вы просите, используя подсистему фокуса:
import java.awt.Component;
import java.awt.Container;
import java.awt.DefaultFocusTraversalPolicy;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class FocusHopSystem {
public static class AbsoluteFocusTraversalPolicy extends DefaultFocusTraversalPolicy {
private final Component[] comps;
public AbsoluteFocusTraversalPolicy(final Component... comps) {
this.comps = comps.clone();
}
private int indexOf(final Component comp) {
for (int i = 0; i < comps.length; ++i)
if (comps[i] == comp)
return i;
return -1;
}
@Override
public Component getComponentAfter(final Container aContainer, final Component aComponent) {
final int aIndex = indexOf(aComponent);
if (aIndex < 0)
return null;
for (int i = 1; i < comps.length; ++i) {
final Component after = comps[(aIndex + i) % comps.length];
if (after != null && after.isDisplayable() && after.isVisible() && after.isEnabled())
return after;
}
return null;
}
@Override
public Component getComponentBefore(final Container aContainer, final Component aComponent) {
final int aIndex = indexOf(aComponent);
if (aIndex < 0)
return null;
for (int i = 1; i < comps.length; ++i) {
final Component before = comps[(aIndex - i + comps.length) % comps.length];
if (before != null && before.isDisplayable() && before.isVisible() && before.isEnabled())
return before;
}
return null;
}
@Override
public Component getFirstComponent(final Container aContainer) {
for (int i = 0; i < comps.length; ++i) {
final Component first = comps[i];
if (first != null && first.isDisplayable() && first.isVisible() && first.isEnabled())
return first;
}
return null;
}
@Override
public Component getLastComponent(final Container aContainer) {
for (int i = comps.length - 1; i >= 0; --i) {
final Component last = comps[i];
if (last != null && last.isDisplayable() && last.isVisible() && last.isEnabled())
return last;
}
return null;
}
@Override
public Component getDefaultComponent(final Container aContainer) {
return getFirstComponent(aContainer);
}
}
private static void createAndShowGUI() {
final String text = "0";
final int width = 12;
final JTextField tf1 = new JTextField(text, width),
tf2 = new JTextField(text, width),
tf3 = new JTextField(text, width),
tf4 = new JTextField(text, width);
final JCheckBox ck2 = new JCheckBox("jTextField2", true),
ck3 = new JCheckBox("jTextField3", true),
ck4 = new JCheckBox("jTextField4", true);
final JButton save = new JButton("Save");
ck2.addActionListener(e -> tf2.setEnabled(ck2.isSelected()));
ck3.addActionListener(e -> tf3.setEnabled(ck3.isSelected()));
ck4.addActionListener(e -> tf4.setEnabled(ck4.isSelected()));
final JPanel frameContents = new JPanel(new GridLayout(0, 5, 5, 5));
//First row:
frameContents.add(new JPanel());
frameContents.add(ck2);
frameContents.add(ck3);
frameContents.add(ck4);
frameContents.add(new JPanel());
//Second row:
frameContents.add(tf1);
frameContents.add(tf2);
frameContents.add(tf3);
frameContents.add(tf4);
frameContents.add(save);
//Make the other components unfocusable:
for (final Component comp: new Component[]{ck2, ck3, ck4, save})
comp.setFocusable(false);
//Make frameContents the focus cycle root:
frameContents.setFocusCycleRoot(true);
//Install our FocusTraversalPolicy to the cycle root:
frameContents.setFocusTraversalPolicy(new AbsoluteFocusTraversalPolicy(tf1, tf2, tf3, tf4));
//Add KeyEvent.VK_ENTER key to the focus traversal keys of the frameContents:
final Set forwardKeys = frameContents.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
final Set newForwardKeys = new HashSet(forwardKeys);
newForwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
frameContents.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
final JFrame frame = new JFrame("Focus traversal test.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(frameContents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//Start focus on the first text field:
tf1.requestFocusInWindow();
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(FocusHopSystem::createAndShowGUI);
}
}
В приведенном выше примере я добавляю клавиша ENTER в качестве альтернативной клавиши обхода фокуса, помимо TAB .
Edit 1: Это еще проще ...
Как я обнаружил вне, это даже проще, чем в первом примере кода, и это потому, что политика обхода фокуса по умолчанию делает то, что вы просите, ie позволяет только фокусируемым и включенным компонентам получать фокус и в желаемом порядке. Поэтому нам нужно только сделать ненужные компоненты нефокусируемыми (ie флажки и кнопки) и оставить активными текстовые поля. Просто добавьте / установите клавишу ENTER в качестве клавиши обхода фокуса, и вы можете go:
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class FocusHopSystem2 {
private static void createAndShowGUI() {
final String text = "0";
final int width = 12;
final JTextField tf1 = new JTextField(text, width),
tf2 = new JTextField(text, width),
tf3 = new JTextField(text, width),
tf4 = new JTextField(text, width);
final JCheckBox ck2 = new JCheckBox("jTextField2", true),
ck3 = new JCheckBox("jTextField3", true),
ck4 = new JCheckBox("jTextField4", true);
final JButton save = new JButton("Save");
ck2.addActionListener(e -> tf2.setEnabled(ck2.isSelected()));
ck3.addActionListener(e -> tf3.setEnabled(ck3.isSelected()));
ck4.addActionListener(e -> tf4.setEnabled(ck4.isSelected()));
final JPanel frameContents = new JPanel(new GridLayout(0, 5, 5, 5));
//First row:
frameContents.add(new JPanel());
frameContents.add(ck2);
frameContents.add(ck3);
frameContents.add(ck4);
frameContents.add(new JPanel());
//Second row:
frameContents.add(tf1);
frameContents.add(tf2);
frameContents.add(tf3);
frameContents.add(tf4);
frameContents.add(save);
//Make the other components unfocusable:
for (final Component comp: new Component[]{ck2, ck3, ck4, save})
comp.setFocusable(false);
//Make frameContents the focus cycle root:
frameContents.setFocusCycleRoot(true);
////Install the DefaultFocusTraversalPolicy to the cycle root:
//frameContents.setFocusTraversalPolicy(new DefaultFocusTraversalPolicy()); //This is not necessary in this case.
//Add KeyEvent.VK_ENTER key to the focus traversal keys of the frameContents:
final Set forwardKeys = frameContents.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
final Set newForwardKeys = new HashSet(forwardKeys);
newForwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
frameContents.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
final JFrame frame = new JFrame("Focus traversal test.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(frameContents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//Start focus on the first text field:
tf1.requestFocusInWindow();
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(FocusHopSystem2::createAndShowGUI);
}
}
Вы также можете прочитать Подсистема AWT Focus .