早期 Java 依賴本地窗口管理器處理焦點,導致跨平台不一致。Java 1.4 (Merlin) 引入全新 AWT 級焦點子系統,核心是集中式 KeyboardFocusManager,統一管理活動窗口、焦點擁有者及遍歷策略,雖帶來不兼容風險,但解決了長期困擾開發者的平台差異問題。
這是一個抽象類而非接口,控制焦點循環根內的遍歷順序。焦點循環根(focusCycleRoot=true 的容器)將焦點限制在內部組件循環中。默認窗口/框架為根,其他容器需顯式設置。
| 方法 | 用途 | 抽象性 |
|---|---|---|
getDefaultComponent(Container) | 根獲取焦點時的默認組件(向下循環入口) | 抽象 |
getInitialComponent(Window) | 窗口首次顯示時的初始焦點組件 | 具體(默認調用 getDefaultComponent) |
getComponentBefore(Container, Component) | Shift+Tab 反向遍歷 | 抽象 |
getComponentAfter(Container, Component) | Tab 正向遍歷 | 抽象 |
getFirstComponent(Container) | 循環起始組件 | 抽象 |
getLastComponent(Container) | 循環終止組件 | 抽象 |
getComponents() 數組)JInternalFrame 設計Comparator 自定義排序邏輯另有非公共的 LegacyGlueFocusTraversalPolicy 兼容舊版 setNextFocusableComponent()。
import java.awt.*;
import javax.swing.*;
import java.util.Arrays;
import java.util.List;
public class BorderFocusDemo {
public static void main(String[] args) {
JFrame frame = new JFrame("焦點循環演示");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = frame.getContentPane();
// BorderLayout 五大區域按鈕
JButton north = new JButton("North");
JButton south = new JButton("South");
JButton east = new JButton("East");
JButton west = new JButton("West");
JButton center = new JButton("Center");
cp.add(north, BorderLayout.NORTH);
cp.add(south, BorderLayout.SOUTH);
cp.add(east, BorderLayout.EAST);
cp.add(west, BorderLayout.WEST);
cp.add(center, BorderLayout.CENTER);
cp.setFocusable(false); // 容器自身不可聚焦
// 定義遍歷順序:北 → 東 → 南 → 西 → 中
final Component[] order = {north, east, south, west, center};
FocusTraversalPolicy policy = new FocusTraversalPolicy() {
List list = Arrays.asList(order);
public Component getFirstComponent(Container root) { return order[0]; }
public Component getLastComponent(Container root) { return order[order.length - 1]; }
public Component getComponentAfter(Container root, Component comp) {
int idx = list.indexOf(comp);
return order[(idx + 1) % order.length];
}
public Component getComponentBefore(Container root, Component comp) {
int idx = list.indexOf(comp);
return order[(idx - 1 + order.length) % order.length];
}
public Component getDefaultComponent(Container root) { return order[0]; }
};
frame.setFocusTraversalPolicy(policy);
frame.pack();
frame.setVisible(true);
}
}
requestFocus() 應改為 requestFocusInWindow()setFocusTraversalKeys() 自定義