JAVA組件焦點的特性:其組件的頂層祖先必須爲可見的。
requestFocus,requestFocusInWindow等這些方法在獲取組件焦點時都提到了:
請求此 Component 獲取輸入焦點,並且此 Component 的頂層祖先成爲獲得焦點的 Window。此 Component 對於所要許可的請求而言必須是不可顯示的、可聚焦的和可見的並且其所有祖先(除了頂層 Window 以外)必須是可見的。此方法會盡力完成該請求;但是在某些情況下可能無法完成。在此 Component 接收 FOCUS_GAINED 事件前,開發人員永遠不能假定此 Component 是焦點所有者。如果由於此 Component
的頂層 Window 沒有成爲獲得焦點的窗口而拒絕了此請求,則記住此請求,並在後來用戶使窗口成爲獲得焦點的窗口時許可此請求。
參考源碼:Component的源碼
Component window = this;
while ( (window != null) && !(window instanceof Window)) {
if (!window.isVisible()) {
if (focusLog.isLoggable(PlatformLogger.FINEST)) {
focusLog.finest("component is recurively invisible");
}
return false;
}
window = window.parent;
}
例子:
import java.awt.event.*;
import javax.swing.*;
public class two{
public static void main(String args[]){
final JFrame jf = new JFrame();
A a = new A();
jf.setSize(400,500);
jf.add(a);
jf.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
System.out.println("you");
}
}
});
a.requestFocus();
jf.setVisible(true);
jf.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
jf.requestFocus();
}
});
//a.requestFoucus();
}
}
class A extends JPanel{
public A() {
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
System.out.println("左");
}
}
});
}
}
代碼簡單說明:在two類中有一個窗體jf,對鍵盤事件監聽,按下“←”,控制檯打印出“you”,同時在Main方法中new出一個JPanel對象a,在類A中的構造方法中添加了鍵盤事件監聽,按下“←”,控制檯打印出“左”。同時爲了實驗,窗體jf實現了點擊鼠標就會獲得焦點。實驗一:a對象調用requestFocus()方法獲得焦點後,窗體 jf 才顯示。此時按下←鍵後,顯示“you”。
實驗二:窗體jf 先顯示 再讓a對象調用requestFocus()方法獲得焦點。此時按下←鍵後,顯示“左”。此時點擊窗體,再按下←鍵後,顯示“you”。
疑問:在實驗一的情況下,如果點擊JPanel所在處是否能獲得JPanel的焦點呢?
窗體初始化時,此時焦點的擁有者爲jf,(註釋掉jf的監聽鼠標事件後),點擊JPanel的位置,測試結果仍爲“you”。所以說明點擊鼠標不能獲得焦點。
結論:組件獲取焦點時,其頂層容器必須可見。