Próbuję zaimplementować plik KeyListener
dla mojego JFrame
. W konstruktorze używam tego kodu:
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"); }
});
Kiedy go uruchamiam, na test
mojej konsoli pojawia się komunikat. Jednak po naciśnięciu klawisza nie dostaję żadnych innych komunikatów, jakby ich KeyListener
tam nawet nie było.
Myślałem, że może to być spowodowane tym, że nie koncentruje się na nich, JFrame
więc KeyListener
nie otrzymują żadnych wydarzeń. Ale jestem prawie pewien, że tak.
Czy jest coś, czego mi brakuje?
źródło
Jeśli nie chcesz rejestrować nasłuchiwania w każdym komponencie,
możesz dodać własne
KeyEventDispatcher
doKeyboardFocusManager
: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); } }
źródło
InputMaps i ActionMaps zostały zaprojektowane w celu przechwytywania kluczowych zdarzeń dla komponentu, go i wszystkich jego podkomponentów lub całego okna. Jest to kontrolowane przez parametr w JComponent.getInputMap (). Zobacz dokumentację, jak używać powiązań klawiszy .
Piękno tego projektu polega na tym, że można wybrać i wybrać, które naciśnięcia klawiszy są ważne do monitorowania, i wyzwalać różne akcje w oparciu o te naciśnięcia klawiszy.
Ten kod wywoła dispose () na JFrame, gdy klawisz Escape zostanie naciśnięty w dowolnym miejscu w oknie. JFrame nie pochodzi od JComponent, więc musisz użyć innego komponentu w JFrame, aby utworzyć powiązanie klucza. Takim składnikiem może być panel zawartości.
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);
źródło
KeyListener
jest niski i dotyczy tylko jednego komponentu. Pomimo prób uczynienia go bardziej użytecznymJFrame
tworzy szereg komponentów składowych, z których najbardziej oczywistym jest panel zawartości.JComboBox
Interfejs użytkownika jest często implementowany w podobny sposób.Warto zauważyć, że zdarzenia myszy działają w dziwny sposób, nieco inaczej niż zdarzenia kluczowe.
Szczegółowe informacje na temat tego, co należy zrobić, można znaleźć w mojej odpowiedzi na temat skrótu klawiaturowego dla całej aplikacji - Java Swing .
źródło
Mam ten sam problem, dopóki nie przeczytałem, że prawdziwy problem dotyczy FOCUSa, twój JFrame już dodał Słuchacze, ale ramka trasy nigdy nie jest w Focus, ponieważ masz wiele komponentów wewnątrz swojej JFrame, które również można ustawić, więc spróbuj:
JFrame.setFocusable(true);
Powodzenia
źródło
Deion (i każdy inny zadający podobne pytanie), możesz użyć powyższego kodu Petera, ale zamiast drukować na standardowe wyjście, testujesz pod kątem kodu klawisza PRESSED, RELEASED lub 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; }
źródło
aby uchwycić kluczowe zdarzenia WSZYSTKICH pól tekstowych w JFrame , można zastosować postprocesor kluczowych zdarzeń. Oto działający przykład po dodaniu oczywistych dołączeń.
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; } }
źródło
Hmm ... do jakiej klasy jest twój konstruktor? Prawdopodobnie JFrame rozszerzający klasę? Fokus okna powinien oczywiście znajdować się w oknie, ale nie sądzę, że to jest problem.
Rozszerzyłem twój kod, próbowałem go uruchomić i zadziałało - naciśnięcia klawiszy skutkowały wydrukowaniem. (uruchom z Ubuntu przez Eclipse):
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); } }
źródło
To powinno pomóc
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"); } });
źródło
Miałem ten sam problem. Postępowałem zgodnie z radą Bruno i stwierdziłem, że dodanie KeyListenera tylko do „pierwszego” przycisku w JFrame (tj. W lewym górnym rogu) załatwiło sprawę. Ale zgadzam się z tobą, jest to dość niepokojące rozwiązanie. Więc pogrzebałem i odkryłem zgrabniejszy sposób, aby to naprawić. Po prostu dodaj linię
do głównej metody, po utworzeniu instancji podklasy JFrame i ustawieniu jej jako widocznej.
źródło
lol .... wszystko, co musisz zrobić, to się upewnić
addKeyListener (this);
jest poprawnie umieszczony w kodzie.
źródło
Możesz mieć niestandardowe komponenty JComponents, które ustawią ich nadrzędną ramkę JFrame jako aktywną.
Po prostu dodaj konstruktora i przekaż JFrame. Następnie wywołaj metodę setFocusable () w paintComponent.
W ten sposób JFrame zawsze otrzyma KeyEvents, niezależnie od tego, czy inne komponenty są wciśnięte.
źródło