2016-04-14 101 views
2

我在JFrame的根窗格註冊了一個事件,該窗格在按下空格鍵(打開另一個窗口)時會作出反應。我在這個JFrame裏面也有一個JTextField。當用戶處於我的文本字段的編輯模式並擊中空格鍵時,空間事件只能被文本字段消耗,不會被轉發到JFrame的動作圖。在JTextField中點擊空格鍵會觸發父窗口的鍵綁定

我該怎麼做?

這是問題的一個可運行的演示:

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 

public class TestDialog { 

    public static void main(String[] args) { 
     JFrame frame = new JFrame(); 
     frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaceAction"); 
     frame.getRootPane().getActionMap().put("spaceAction", new AbstractAction() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("spaceAction"); 
      } 
     }); 
     JTextField tf = new JTextField("textfield"); 
     JLabel label = new JLabel("otherComponent"); 
     label.setFocusable(true); 
     frame.getContentPane().setLayout(new FlowLayout()); 
     frame.getContentPane().add(tf); 
     frame.getContentPane().add(label); 
     frame.pack(); 
     frame.setVisible(true); 

    } 

} 
+0

你使用了什麼InputMap級別?也許考慮提供一個演示你的問題的可運行示例 – MadProgrammer

+0

添加了一個演示應用程序 – trainrobbery

+0

我嘗試了所有3個InputMap級別,它們按預期工作(ancestor_of_focussed_comp,when_in_focussed_window,when_focussed),前兩個按我描述的工作,第三級別不起作用根本沒有,因爲根窗格不能有焦點,不應該 – trainrobbery

回答

1

它不使用空格鍵作爲一個全球性的觸發一個好主意。但是,如果你真的需要它在這裏是這樣的:

import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 

import javax.swing.AbstractAction; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 
import javax.swing.text.JTextComponent; 

public class DialogTest { 
    public static void main(String[] args) { 
     JFrame frame = new JFrame(); 
     frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaceAction"); 
     frame.getRootPane().getActionMap().put("spaceAction", new AbstractAction() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (EventQueue.getCurrentEvent() instanceof KeyEvent) { 
        KeyEvent ke = (KeyEvent) EventQueue.getCurrentEvent(); 
        if (!(ke.getComponent() instanceof JTextComponent)) { 
         System.out.println("spaceAction"); 
        } else { 
         System.out.println("Ignore event in text component"); 
        } 
       } else { 
        System.out.println("spaceAction"); 
       } 
      } 
     }); 
     JTextField tf = new JTextField("textfield"); 
     JLabel label = new JLabel("otherComponent"); 
     label.setFocusable(true); 
     frame.getContentPane().setLayout(new FlowLayout()); 
     frame.getContentPane().add(tf); 
     frame.getContentPane().add(label); 
     frame.pack(); 
     frame.setVisible(true); 

    } 

} 

更好的方法是特拉弗斯組件樹從根開始窗格,並添加鍵綁定只爲你需要(例如所有標籤)的組件。這裏是我的遍歷方法

/** 
* Searches for all children of the given component which are instances of the given class. 
* 
* @param aRoot start object for search. 
* @param aClass class to search. 
* @param <E> class of component. 
* @return list of all children of the given component which are instances of the given class. Never null. 
*/ 
public static <E> List<E> getAllChildrenOfClass(Container aRoot, Class<E> aClass) { 
    final List<E> result = new ArrayList<E>(); 
    final Component[] children = aRoot.getComponents(); 
    for (final Component c : children) { 
     if (aClass.isInstance(c)) { 
      result.add(aClass.cast(c)); 
     } 
     if (c instanceof Container) { 
      result.addAll(getAllChildrenOfClass((Container) c, aClass)); 
     } 
    } 
    return result; 
} 
+0

我用你的第一個解決方案解決了它,謝謝。但是,這是一個功能還是JTextField轉發已經消費的鍵盤字符的錯誤? – trainrobbery

+0

@trainrobbery我認爲這是一個功能。在某些情況下,可能需要多個事件處理。 –

相關問題