視窗啟動時讓 JTextField 直接獲得輸入焦點(游標閃爍),且使用者點擊同視窗內的 JTextArea 時,焦點自動跳回 JTextField,實現「焦點鎖定」效果。
Component.requestFocusInWindow():請求焦點,較 requestFocus() 更可靠。Window.addWindowFocusListener / ComponentListener:視窗顯示後再請求焦點,避免視窗未顯示導致失效。MouseListener:攔截 JTextArea 滑鼠點擊並轉移焦點。import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class FocusLockDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("焦點鎖定示範");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout(10, 10));
frame.setSize(400, 300);
JTextField lockedField = new JTextField(20);
lockedField.setName("lockedField");
JTextArea freeArea = new JTextArea(5, 20);
freeArea.setText("點擊這裡,焦點會跳回上方輸入框");
freeArea.setLineWrap(true);
freeArea.setWrapStyleWord(true);
// 1. 視窗顯示後讓 lockedField 獲得焦點
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
lockedField.requestFocusInWindow();
}
});
// 2. 攔截 JTextArea 滑鼠點擊,強制焦點回到 lockedField
freeArea.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
lockedField.requestFocusInWindow();
}
});
frame.add(lockedField, BorderLayout.NORTH);
frame.add(new JScrollPane(freeArea), BorderLayout.CENTER);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
若需更徹底禁止 JTextArea 獲得焦點(連 Tab 鍵也不行),可自訂 FocusTraversalPolicy:
frame.setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() {
@Override
public Component getComponentAfter(Container focusCycleRoot, Component aComponent) {
return lockedField; // 永遠回到 lockedField
}
@Override
public Component getComponentBefore(Container focusCycleRoot, Component aComponent) {
return lockedField;
}
@Override
public Component getDefaultComponent(Container focusCycleRoot) {
return lockedField;
}
});
| 現象 | 原因 | 解決 |
|---|---|---|
| 啟動時焦點不在 JTextField | 在構造元件時呼叫 requestFocus,視窗尚未顯示 | 改用 WindowListener.windowOpened 或 invokeLater 延後執行 |
| 點擊 JTextArea 仍能輸入 | 未消費滑鼠事件,焦點轉移後又被 JTextArea 取回 | 在 mousePressed 呼叫 requestFocusInWindow,並可加上 e.consume() |
| Tab 鍵仍能切換到 JTextArea | 預設 FocusTraversalPolicy 允許 | 自訂 FocusTraversalPolicy 或設定 freeArea.setFocusable(false) |
「啟動自動聚焦 + 滑鼠點擊攔截轉移」是最直觀的焦點鎖定做法;若需完全移除元件的焦點能力,配合 setFocusable(false) 或自訂 FocusTraversalPolicy 效果最佳。