К счастью, у меня есть гораздо меньший пример пользовательской формы, где я добавил политику обхода фокуса.
Код состоит из двух частей. Пока я создаю GUI, я устанавливаю свою политику обхода фокуса. Я поместил все поля JTextFields в список в том порядке, в котором я хочу их обойти. Каждое редактируемое поле в JPanel должно быть включено в этот список.
Я также написал класс, который расширяет FocusTraversalPolicy. Я сделал это частным и включил его в класс представления. Это кажется подходящим местом для занятий. Вы можете поместить его в отдельный файл, если хотите.
Вот код. Вы можете скомпилировать его, запустить и увидеть, что табуляция через форму следует за столбцами. Это то, что мы хотели бы назвать минимальным воспроизводимым примером .
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FocusTraversalPolicy;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
public class UserForm {
// top, left, bottom, right
private static final Insets topInsets = new Insets(10, 10, 10, 10);
private static final Insets topCenterInsets = new Insets(10, 0, 10, 10);
private static final Insets middleInsets = new Insets(0, 10, 10, 10);
private static final Insets middleCenterInsets = new Insets(0, 0, 10, 10);
public UserForm() {
JFrame frame = new JFrame("User Form");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Miscelaneous
Font plain = new Font("Tahoma", Font.PLAIN, 12);
Font bold11 = new Font("Tahoma", Font.BOLD, 11);
Font bold12 = new Font("Tahoma", Font.BOLD, 12);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
int gridy = 0;
// Data-In Form Components
JLabel idl = new JLabel("Id:");
idl.setFont(bold12);
addComponent(mainPanel, idl, 0, gridy, 1, 1, topInsets, GridBagConstraints.LINE_START, GridBagConstraints.NONE);
JTextField idtf = new JTextField(40);
idtf.setFont(plain);
addComponent(mainPanel, idtf, 1, gridy, 1, 1, topCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel agl = new JLabel("Age:");
agl.setFont(bold12);
addComponent(mainPanel, agl, 2, gridy, 1, 1, topCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField agtf = new JTextField(40);
agtf.setFont(plain);
addComponent(mainPanel, agtf, 3, gridy++, 1, 1, topCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel namel = new JLabel("Name:");
namel.setFont(bold12);
addComponent(mainPanel, namel, 0, gridy, 1, 1, middleInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField nametf = new JTextField(40);
nametf.setFont(plain);
addComponent(mainPanel, nametf, 1, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel adl = new JLabel("Address:");
adl.setFont(bold12);
addComponent(mainPanel, adl, 2, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField adtf = new JTextField(40);
adtf.setFont(plain);
addComponent(mainPanel, adtf, 3, gridy++, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel pnl = new JLabel("Phone Number:");
pnl.setFont(bold12);
addComponent(mainPanel, pnl, 0, gridy, 1, 1, middleInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField pntf = new JTextField(40);
pntf.setFont(plain);
addComponent(mainPanel, pntf, 1, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel ln1l = new JLabel("First Lastname:");
ln1l.setFont(bold12);
addComponent(mainPanel, ln1l, 2, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField ln1tf = new JTextField(40);
ln1tf.setFont(plain);
addComponent(mainPanel, ln1tf, 3, gridy++, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel ln2l = new JLabel("Second Lastname:");
ln2l.setFont(bold12);
addComponent(mainPanel, ln2l, 0, gridy, 1, 1, middleInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField ln2tf = new JTextField(40);
ln2tf.setFont(plain);
addComponent(mainPanel, ln2tf, 1, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
JLabel eml = new JLabel("E-Mail:");
eml.setFont(bold12);
addComponent(mainPanel, eml, 2, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.NONE);
JTextField emtf = new JTextField(40);
emtf.setFont(plain);
addComponent(mainPanel, emtf, 3, gridy++, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
List<Component> order = new ArrayList<>(8);
order.add(idtf);
order.add(nametf);
order.add(pntf);
order.add(ln2tf);
order.add(agtf);
order.add(adtf);
order.add(ln1tf);
order.add(emtf);
MyOwnFocusTraversalPolicy newPolicy = new MyOwnFocusTraversalPolicy(order);
frame.setFocusTraversalPolicy(newPolicy);
// JTable Creation
String[] headline = { "Id", "Name", "First Lastname", "Second Lastname", "Age", "Address", "Phone Number",
"E-Mail" };
String[][] data = { { "", "", "", "", "", "", "", "" }, { "", "", "", "", "", "", "", "" } };
JTable dataShow = new JTable(data, headline);
dataShow.setPreferredScrollableViewportSize(new Dimension(900, 300));
dataShow.setFillsViewportHeight(true);
JScrollPane scrollPane = new JScrollPane(dataShow);
addComponent(mainPanel, scrollPane, 0, gridy++, 4, 1, middleInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
// Table Personalization
dataShow.getTableHeader().setFont(bold11);
new HeaderRenderer(dataShow);
// buttons Components
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridBagLayout());
JButton save = new JButton("Save");
save.setFont(bold12);
addComponent(buttonPanel, save, 0, 0, 1, 1, topInsets, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL);
JButton del = new JButton("Delete");
del.setFont(bold12);
addComponent(buttonPanel, del, 1, 0, 1, 1, topInsets, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
JButton edit = new JButton("Edit");
edit.setFont(bold12);
addComponent(buttonPanel, edit, 2, 0, 1, 1, topInsets, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL);
addComponent(mainPanel, buttonPanel, 0, gridy++, 4, 1, middleInsets, GridBagConstraints.LINE_START,
GridBagConstraints.HORIZONTAL);
// set content pane
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
// For future table filling
/*
* String ids = idtf.getText(); String names = nametf.getText(); String ln1s =
* ln1tf.getText(); String ln2s = ln2tf.getText(); String ags = agtf.getText();
* String ads = adtf.getText(); String pns = pntf.getText(); String ems =
* emtf.getText();
*/
}
private void addComponent(Container container, Component component, int gridx, int gridy, int gridwidth,
int gridheight, Insets insets, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0, 1.0, anchor, fill,
insets, 0, 0);
container.add(component, gbc);
}
public static void main(String[] args) {
// invoke runnable for thread safety
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new UserForm();
}
});
}
// LEFT alignment renderer
private class HeaderRenderer implements TableCellRenderer {
DefaultTableCellRenderer renderer;
public HeaderRenderer(JTable table) {
renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.LEFT);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int col) {
return renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
}
}
private class MyOwnFocusTraversalPolicy extends FocusTraversalPolicy {
private List<Component> componentList;
public MyOwnFocusTraversalPolicy(List<Component> componentList) {
this.componentList = componentList;
}
@Override
public Component getComponentAfter(Container aContainer, Component aComponent) {
int index = getComponentIndex(aComponent);
index++;
index = (index >= componentList.size()) ? 0 : index;
return componentList.get(index);
}
@Override
public Component getComponentBefore(Container aContainer, Component aComponent) {
int index = getComponentIndex(aComponent);
index--;
index = (index < 0) ? index + componentList.size() : index;
return componentList.get(index);
}
@Override
public Component getFirstComponent(Container aContainer) {
return componentList.get(0);
}
@Override
public Component getLastComponent(Container aContainer) {
return componentList.get(componentList.size() - 1);
}
@Override
public Component getDefaultComponent(Container aContainer) {
return componentList.get(0);
}
private int getComponentIndex(Component test) {
for (int i = 0; i < componentList.size(); i++) {
Component component = componentList.get(i);
if (component.equals(test)) {
return i;
}
}
return -1;
}
}
}