Zielony Smok - logo witryny

Własna java.awt.FocusTraversalPolicy

W przypadku przenoszenia fokusu pomiędzy komponentami Swing czasem konieczne jest zastosowanie własnej polityki określającej sposób i kolejność przenoszenia fokusu.

Klasy

Klasa NewFocusTraversalPolicy
package java_awt_focustraversalppolicy;
import java.awt.*;
import java.util.*;
import javax.swing.*;
//Jeżeli użyjemy klawisza tab to fokus będzie się
//przenosił jedynie miedzy elementami umieszczonymi
//w wektorze w takiej kolejności w jakiej one sa w nim
//umieszczone
@SuppressWarnings("SuspiciousMethodCalls")
public class NewFocusTraversalPolicy extends FocusTraversalPolicy {
    private final Vector<JComponent> order;
    public NewFocusTraversalPolicy(Vector<JComponent> order) {
        this.order = new Vector<>(order.size());
        this.order.addAll(order);
    }
    @Override
    public Component getComponentAfter(Container focusCycleRoot,
                                       Component component) {
        int idx = (order.indexOf(component) + 1) % order.size();
        return order.get(idx);
    }
    @Override
    public Component getComponentBefore(Container focusCycleRoot,
                                        Component component) {
        int idx = order.indexOf(component) - 1;
        if (idx < 0) {
            idx = order.size() - 1;
        }
        return order.get(idx);
    }
    @Override
    public Component getDefaultComponent(Container focusCycleRoot) {
        return order.get(0);
    }
    @Override
    public Component getFirstComponent(Container focusCycleRoot) {
        return order.get(0);
    }
    @Override
    public Component getLastComponent(Container container) {
        return order.lastElement();
    }
}
Klasa Main
package java_awt_focustraversalppolicy;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class Main extends JFrame {
    private static final long serialVersionUID = 5990924180312145579L;
    public Main() {
        setLayout(new FlowLayout());
        Vector<JComponent> vector = new Vector<>();
        JButton[] buttons = new JButton[11];
        // dodanie komponentów które będą miały focus
        // i w takiej kolejności w jakiej ten fokus
        // będzie przekazywany
        for (int i = 0; i < 11; i++) {
            buttons[i] = new JButton(Integer.toString(i));
            add(buttons[i]);
            if (i % 2 == 0) {
                vector.add(buttons[i]);
            }
        }
        NewFocusTraversalPolicy policy = new NewFocusTraversalPolicy(vector);
        setFocusTraversalPolicy(policy);
        setBounds(10, 100, 300, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(Main::new);
    }
}
Wynik

W klasie Main dodajemy do wektora co drugi przycisk, tworzymy klasę polityki.

Gdy uruchomimy klasę i klawiszem tab będziemy zmieniali fokus, zobaczymy, że fokus otrzymują tylko przyciski umieszczone w wektorze.

Na wideo pokazano wynik kilkukrotnego naciśnięcia przycisku TAB