[英]Unresponsive KeyListener for JFrame
我正在嘗試為JFrame
實現KeyListener
。 在構造函數上,我使用以下代碼:
System.out.println("test");
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) { System.out.println( "tester"); }
public void keyReleased(KeyEvent e) { System.out.println("2test2"); }
public void keyTyped(KeyEvent e) { System.out.println("3test3"); }
});
當我運行它時, test
消息會出現在我的控制台中。 但是,當我按一個鍵時,沒有收到其他任何消息,就好像KeyListener
不在那兒一樣。
我在想這可能是因為重點不在JFrame
因此,它們的KeyListener
不會收到任何事件。 但是,我很確定。
有什么我想念的嗎?
如果您不想在每個組件上注冊一個偵聽器,
您可以將自己的KeyEventDispatcher
添加到KeyboardFocusManager
:
public class MyFrame extends JFrame {
private class MyDispatcher implements KeyEventDispatcher {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
System.out.println("tester");
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
System.out.println("2test2");
} else if (e.getID() == KeyEvent.KEY_TYPED) {
System.out.println("3test3");
}
return false;
}
}
public MyFrame() {
add(new JTextField());
System.out.println("test");
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(new MyDispatcher());
}
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.pack();
f.setVisible(true);
}
}
您必須將keyListener添加到所需的每個組件中。 僅具有焦點的組件將發送這些事件。 例如,如果JFrame中只有一個TextBox,則該TextBox具有焦點。 因此,您還必須將KeyListener添加到此組件。
過程是一樣的:
myComponent.addKeyListener(new KeyListener ...);
注意:某些組件無法像JLabel那樣聚焦。
要將它們設置為可聚焦,您需要:
myComponent.setFocusable(true);
InputMap和ActionMap旨在捕獲組件,組件及其所有子組件或整個窗口的鍵事件。 這是通過JComponent.getInputMap()中的參數控制的。 有關文檔,請參見如何使用鍵綁定 。
此設計的優點在於,可以選擇並選擇哪些按鍵對於監視非常重要,並根據這些按鍵觸發不同的動作。
當在窗口中的任意位置按下轉義鍵時,此代碼將在JFrame上調用dispose()。 JFrame不是從JComponent派生的,因此您必須使用JFrame中的另一個組件來創建鍵綁定。 內容窗格可能就是這樣的組件。
InputMap inputMap;
ActionMap actionMap;
AbstractAction action;
JComponent component;
inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
actionMap = component.getActionMap();
action = new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
dispose();
}
};
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose");
actionMap.put("dispose", action);
KeyListener
是低級別的,僅適用於單個組件。 盡管試圖使它變得更有用,但JFrame
創建了許多組件組件,最明顯的是內容窗格。 JComboBox
UI通常也以類似的方式實現。
值得注意的是,鼠標事件的工作方式與鍵事件略有不同。
有關應執行的操作的詳細信息,請參見我關於應用程序級鍵盤快捷鍵-Java Swing的答復。
我遇到了同樣的問題,直到我讀到真正的問題是關於FOCUS的問題為止,您的JFrame已經添加了偵聽器,但是巡視框架從來沒有放在Focus上,因為您在JFrame中擁有很多可以聚焦的組件,所以請嘗試:
JFrame.setFocusable(true);
祝好運
Deion(以及其他提出類似問題的人),您可以使用上面的Peter的代碼,但是可以打印關鍵代碼PRESSED,RELEASED或TYPED,而不是打印到標准輸出。
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
if (e.getKeyCode() == KeyEvent.VK_F4) {
dispose();
}
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
if (e.getKeyCode() == KeyEvent.VK_F4) {
dispose();
}
} else if (e.getID() == KeyEvent.KEY_TYPED) {
if (e.getKeyCode() == KeyEvent.VK_F4) {
dispose();
}
}
return false;
}
為了捕獲JFrame中所有文本字段的鍵事件,可以使用一個鍵事件后處理器。 添加明顯的包含之后,這是一個工作示例。
public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor {
public static final long serialVersionUID = 1L;
public KeyListenerF1Demo() {
setTitle(getClass().getName());
// Define two labels and two text fields all in a row.
setLayout(new FlowLayout());
JLabel label1 = new JLabel("Text1");
label1.setName("Label1");
add(label1);
JTextField text1 = new JTextField(10);
text1.setName("Text1");
add(text1);
JLabel label2 = new JLabel("Text2");
label2.setName("Label2");
add(label2);
JTextField text2 = new JTextField(10);
text2.setName("Text2");
add(text2);
// Register a key event post processor.
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventPostProcessor(this);
}
public static void main(String[] args) {
JFrame f = new KeyListenerF1Demo();
f.setName("MyFrame");
f.pack();
f.setVisible(true);
}
@Override
public boolean postProcessKeyEvent(KeyEvent ke) {
// Check for function key F1 pressed.
if (ke.getID() == KeyEvent.KEY_PRESSED
&& ke.getKeyCode() == KeyEvent.VK_F1) {
// Get top level ancestor of focused element.
Component c = ke.getComponent();
while (null != c.getParent())
c = c.getParent();
// Output some help.
System.out.println("Help for " + c.getName() + "."
+ ke.getComponent().getName());
// Tell keyboard focus manager that event has been fully handled.
return true;
}
// Let keyboard focus manager handle the event further.
return false;
}
}
這應該有幫助
yourJFrame.setFocusable(true);
yourJFrame.addKeyListener(new java.awt.event.KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
System.out.println("you typed a key");
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println("you pressed a key");
}
@Override
public void keyReleased(KeyEvent e) {
System.out.println("you released a key");
}
});
嗯..您的構造函數是什么類的? 可能是一些擴展JFrame的類? 當然,窗口焦點應該在窗口上,但是我不認為這是問題所在。
我擴展了您的代碼,嘗試運行它並成功了-按鍵結果作為打印輸出。 (通過Eclipse與Ubuntu一起運行):
public class MyFrame extends JFrame {
public MyFrame() {
System.out.println("test");
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
System.out.println("tester");
}
public void keyReleased(KeyEvent e) {
System.out.println("2test2");
}
public void keyTyped(KeyEvent e) {
System.out.println("3test3");
}
});
}
public static void main(String[] args) {
MyFrame f = new MyFrame();
f.pack();
f.setVisible(true);
}
}
我一直有同樣的問題。 我聽了Bruno的建議,發現僅在JFrame中的“第一個”按鈕(即,左上方)上添加KeyListener就可以了。 但是我同意你的看法,這是一個令人不安的解決方案。 所以我四處弄弄,發現了一種更整潔的方法來修復它。 只需添加行
myChildOfJFrame.requestFocusInWindow();
創建主JFrame子類的實例並將其設置為可見后,將其轉換為主要方法。
大聲笑..您要做的就是確保
addKeyListener(this);
已正確放置在您的代碼中。
您可以讓自定義JComponent將其父JFrame設置為可聚焦。
只需添加一個構造函數並傳遞JFrame。 然后在paintComponent中調用setFocusable()。
這樣,無論是否按下其他組件,JFrame都將始終接收KeyEvent。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.