Swing KeyListener für JPanel funktioniert nicht

chaostheory

Bekanntes Mitglied
Hallo,
ich schreibe momentan ein 2D-Spiel in Java und habe eben alle Components aus AWT mit JComponents aus Swing ersetzt.
Ich nutze einen JFrame und füge diesem ein JPanel hinzu, auf dem alle JButtons usw. liegen und der auf die Listener hören sollte. Einen Mouse- und einen KeyListener.
Ich habe einfach alles so wie in der vorigen funktionierenden Version gelassen, nur die Listener einfach dem JPanel und nicht dem JFrame zugewiesen. Es funktioniert jedoch nur noch der MouseListener, der KeyListener erhält keine Eingaben.
Ich habe schon herausgefunden, dass Swing nicht threadsicher ist.
Beim Start des Spiels rufe ich normal die Methode createFrame() auf und lade den Rest des Spiels, dann starte ich zwei eigene Threads: Der eine ruft immer die draw()-Methode auf und der andere berechnet die neuen Positionen aller Figuren. Kann das damit zusammenhängen?

JFrame wird erstellt:
Java:
public void createFrame() { 
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        maximizeFrame(getFirstCompatibleMode(displayModes));
	frame.setResizable(false);
        frame.setIgnoreRepaint(true);
        frame.setVisible(true);
        ((JComponent) frame.getContentPane()).setOpaque(false);
 
        JPanel panel = new JPanel();
        main.getComponentHandler().initComponents(panel);
        panel.setOpaque(false);
        panel.addKeyListener(main.getKeyHandler());
		panel.addMouseListener(main.getMouseListener());
		
        frame.getContentPane().add(panel);
 
        frame.createBufferStrategy(2);
	}

Der KeyListener:
Java:
public class KeyHandler implements KeyListener {
	
	private final Main main;
	
	public KeyHandler(Main main) {
		this.main = main;
	}

	@Override
	public void keyPressed(KeyEvent event) {
		System.out.println(event.getKeyCode());
		switch(event.getKeyCode()) {
			case KeyEvent.VK_ESCAPE :	if(main.getStatus() == GameStatus.GAME || main.getStatus() == GameStatus.LEVELCHANGE) main.setStatus(GameStatus.MENU_GAME);
										else if(main.getStatus() == GameStatus.MENU_GAME || main.getStatus() == GameStatus.DEV_MAIN) main.setStatus(GameStatus.GAME); break;
			case KeyEvent.VK_RIGHT :	main.getGameManager().getPlayers().get(0).changeDirection(Player.Direction.RIGHT);	break;
			case KeyEvent.VK_LEFT :		main.getGameManager().getPlayers().get(0).changeDirection(Player.Direction.LEFT);	break;
			case KeyEvent.VK_ENTER :	main.setStatus(GameStatus.GAME);													break;
			case KeyEvent.VK_SPACE :	main.getGameManager().getPlayers().get(0).shootArrow();								break;
		}
		
		event.consume();
	}

	@Override
	public void keyReleased(KeyEvent event) {
		int keyCode = event.getKeyCode();
		
		switch(keyCode) {
			case KeyEvent.VK_RIGHT :	main.getGameManager().getPlayers().get(0).setDirection(Player.Direction.CENTER);	break;
			case KeyEvent.VK_LEFT :		main.getGameManager().getPlayers().get(0).setDirection(Player.Direction.CENTER);	break;
		}
	}

	@Override
	public void keyTyped(KeyEvent event) {}
}

Die alte createFrame()-Methode mit Components aus AWT:
Java:
public void createFrame() {
		frame = new JFrame("Bubble Trouble", graphicsDevice.getDefaultConfiguration());
		frame.setUndecorated(true);
		frame.setIgnoreRepaint(true);
		frame.setResizable(true);
		frame.setFocusable(true);
		maximizeFrame(getFirstCompatibleMode(displayModes));
		
		main.getComponentHandler().initComponents(frame);
		
		frame.addKeyListener(main.getKeyHandler());
		frame.addMouseListener(main.getMouseListener());
		
		frame.setVisible(true);
		
		//Enable double-buffering
		frame.createBufferStrategy(2);
	}
 
Zuletzt bearbeitet:
S

SlaterB

Gast
nach setVisible(true) musst du für das JPanel den Focus anfordern, requestFocus()

generell ist das aber ein unsaubere Sache, der Focus flüchtig,
KeyListener in meinen Augen nur für eindeutig selektierbare Komponenten

KeyBindings ist vielleicht noch eine Alternative


die ersten beiden Absätze im Tutorial
How to Write a Key Listener (The Java™ Tutorials > Creating a GUI With JFC/Swing > Writing Event Listeners)
sind demnach auch
Key events indicate when the user is typing at the keyboard. Specifically, key events are fired by the component with the keyboard focus when the user presses or releases keyboard keys. For detailed information about focus, see How to Use the Focus Subsystem.

Note:
To define special reactions to particular keys, use key bindings instead of a key listener. For further information, see How to Use Key Bindings.
 

chaostheory

Bekanntes Mitglied
Ich hab's jetzt mal mit KeyBindings ausprobiert und es funktioniert einigermaßen. Allerdings verliert das Panel bei jedem Tastendruck den Fokus und ich muss mit der Maus erneut den Bildschirm anklicken, was so auf keinen Fall bleiben kann.
Benutze ich JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT oder JComponent.WHEN_FOCUSED passiert gar nichts.

Java:
panel.registerKeyboardAction(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if(main.getStatus() == GameStatus.GAME || main.getStatus() == GameStatus.LEVELCHANGE) main.setStatus(GameStatus.MENU_GAME);
				else if(main.getStatus() == GameStatus.MENU_GAME || main.getStatus() == GameStatus.DEV_MAIN) main.setStatus(GameStatus.GAME);
			}
		}, KeyStroke.getKeyStroke('a'), JComponent.WHEN_IN_FOCUSED_WINDOW);

Wenn man einem Button ein Event zuweist und JComponent.WHEN_IN_FOCUSED_WINDOW verwendet, funktioniert es fast.
Normalerweise werden alle Eingaben erkannt, aber wenn ich den Button mit setVisivle(false) verstecke, nimmt er auch keine Eingaben an. Allerdings habe ich keine einzige Komponente, die das gesamte Spiel über sichtbar ist!?
 
S

SlaterB

Gast
also bei mir funktionierts
Java:
public class TestGUI  extends JFrame {

    public TestGUI()  {
        JPanel p = new JPanel();
        add(p);
        p.registerKeyboardAction(new ActionListener()    {
                public void actionPerformed(ActionEvent event)  {
                    System.out.println("x");
                }
            }, KeyStroke.getKeyStroke('a'), JComponent.WHEN_IN_FOCUSED_WINDOW);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 400);
        setVisible(true);

    }

    public static void main(String[] args)   {
        new TestGUI();
    }
}
mehrere a hinteineinader führen zu mehreren x-Ausgaben, auch Wechsel auf anderes Fenster und zurück geht
 

chaostheory

Bekanntes Mitglied
Ich habe den Fehler gefunden. Sobald alle Elemente des Panels entweder mit setVisible(false) versteckt, oder mit setEnabled(false) deaktiviert wurden, verliert das Panel seinen Fokus und das war's.
Gibt es da nicht irgendeine Möglichkeit, dem Panel den Fokus wieder zu geben, ohne es bei jedem Buttondruck manuell machen zu müssen?

//edit: Habe eine Lösung gefunden. Da ich eh die Elemente über eine eigene Methode verwende, kann ich dort dem Panel den Fokus geben.
Sonderlich schön finde ich das aber immer noch nicht. Irgendeine bessere Lösung?
 
Zuletzt bearbeitet:
S

SlaterB

Gast
wenn alle Listener von einer gemeinsamen Klasse erben, mit teils gemeinsamer Verarbeitung, darin Focus-Anforderung,
dann wäre es vielleicht nicht so aufwendig,

auch könntest du x.setVisible(y);
durch
show(x) + hide(x)
ersetzen, eigene Methoden, die genau dann an richtiger Stelle auch Focus bearbeitet

selber kann ich mit dieser Art von Ein- und Ausblendung wenig anfangen, auch kein Testprogramm schreiben,
hast du an andere Lösungen wie CardLayout gedacht?
wobei ich nicht sagen kann ob die sich nicht auch auf Focus auswirken
 

chaostheory

Bekanntes Mitglied
Mir hat sich gerade auch noch ein anderes Problem aufgetan: Wie bekomme ich von einem ActionEvent den entsprechenden KeyCode?

Ich habe gerade nochmal drüber geguckt, meine Lösung ist doch recht komfortabel. An allen Stellen, wo wirklich jedes Objekt versteckt wird, wird meine Methode aufgerufen, die dem Panel den Fokus zurück gibt.
Solange der also nicht anderweitig verloren geht, klappt es gut.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C KeyListener für JPanel AWT, Swing, JavaFX & SWT 3
V Tastatur KeyListener für mehrere Buttons AWT, Swing, JavaFX & SWT 1
L KeyListener für JDialog AWT, Swing, JavaFX & SWT 7
B SWT Problem: Wie kann man für jede TableColumn einen eigenen KeyListener registrieren. AWT, Swing, JavaFX & SWT 1
M Fokus für KeyListener AWT, Swing, JavaFX & SWT 9
L Focus für KeyListener auf verschiedene Panels AWT, Swing, JavaFX & SWT 2
K JComboBox und KeyListener für OK-Button AWT, Swing, JavaFX & SWT 6
R KeyListener-Algorithmus für JTextArea AWT, Swing, JavaFX & SWT 3
P JTextfield Text durch Keylistener verändern AWT, Swing, JavaFX & SWT 4
N Keylistener & JComboBox AWT, Swing, JavaFX & SWT 5
B Swing JButton mit KeyListener AWT, Swing, JavaFX & SWT 3
H KeyListener funktioniert nicht AWT, Swing, JavaFX & SWT 1
Fridolin111 Der KeyListener Löst kein event aus AWT, Swing, JavaFX & SWT 6
B KeyListener auf JFrame reagiert nicht AWT, Swing, JavaFX & SWT 8
N Mit KeyListener ein rechteck zeichnen AWT, Swing, JavaFX & SWT 9
S Swing JPanel nimmt keinen KeyListener an AWT, Swing, JavaFX & SWT 7
P JPanel KeyListener hinzufügen AWT, Swing, JavaFX & SWT 8
B Swing KeyListener auf Container? AWT, Swing, JavaFX & SWT 1
T Event Handling KeyListener reagiert nicht AWT, Swing, JavaFX & SWT 10
K KeyListener ohne JFrame AWT, Swing, JavaFX & SWT 9
C Keylistener funktioniert nicht AWT, Swing, JavaFX & SWT 1
T KeyListener funktioniert nicht wenn ich ein JButton hinzufüge AWT, Swing, JavaFX & SWT 1
A Event Handling Muss ich 'KeyListener' tasuend mal zufügen? AWT, Swing, JavaFX & SWT 7
S mit keylistener frame schliessen AWT, Swing, JavaFX & SWT 8
S Keylistener reagiert bei Buttons nicht. AWT, Swing, JavaFX & SWT 8
S KeyListener funktioniert nicht AWT, Swing, JavaFX & SWT 2
R KeyListener in mehreren Panels AWT, Swing, JavaFX & SWT 5
J JLabel Visible setzen in KeyListener AWT, Swing, JavaFX & SWT 13
X KeyListener AWT, Swing, JavaFX & SWT 0
N KeyListener funktioniert nicht richitg AWT, Swing, JavaFX & SWT 4
Z SnakeGame Schlange per KeyListener bewegen! AWT, Swing, JavaFX & SWT 10
T KeyListener AWT, Swing, JavaFX & SWT 2
GianaSisters JFrame mit JInternalFrames, Keylistener-Problem AWT, Swing, JavaFX & SWT 9
7 KeyListener tastatur temporär blockieren AWT, Swing, JavaFX & SWT 7
7 AWT problem: KeyListener/ test im Label umändern AWT, Swing, JavaFX & SWT 4
U Mouse + Keylistener AWT, Swing, JavaFX & SWT 12
K ActionListener mit KeyListener AWT, Swing, JavaFX & SWT 7
J JWindow und keylistener AWT, Swing, JavaFX & SWT 1
F JavaFX KeyListener zum Fenster öffnen/schließen AWT, Swing, JavaFX & SWT 9
A Swing KeyEvent mit KeyListener und KeyAdapter kürzer schreiben AWT, Swing, JavaFX & SWT 7
D JTextArea auf KeyListener Command AWT, Swing, JavaFX & SWT 6
C KeyListener AWT, Swing, JavaFX & SWT 5
Doopy Event Handling KeyListener funktioniert nach Restart nicht mehr AWT, Swing, JavaFX & SWT 7
S KeyListener geht nicht AWT, Swing, JavaFX & SWT 12
C Swing KeyListener in JPanel AWT, Swing, JavaFX & SWT 2
A KeyListener Button wechseln & Programm beenden AWT, Swing, JavaFX & SWT 4
M Frage zu KeyListener bzgl. JApplet AWT, Swing, JavaFX & SWT 3
H Bild mit KeyListener verschieben AWT, Swing, JavaFX & SWT 2
C JTextField KeyListener AWT, Swing, JavaFX & SWT 6
Y KeyListener, GUI Thread, repaint AWT, Swing, JavaFX & SWT 7
bluerob Fehler bei Wertübermittlung über KeyListener AWT, Swing, JavaFX & SWT 3
E Swing KeyListener implementieren AWT, Swing, JavaFX & SWT 12
P KeyListener reagiert nicht AWT, Swing, JavaFX & SWT 11
M KeyListener richtig implementieren AWT, Swing, JavaFX & SWT 3
T KeyListener AWT, Swing, JavaFX & SWT 4
R KeyListener in JWindow AWT, Swing, JavaFX & SWT 7
T BlueJ KeyListener AWT, Swing, JavaFX & SWT 7
Z KeyListener AWT, Swing, JavaFX & SWT 2
M Swing KeyListener in JTextfield AWT, Swing, JavaFX & SWT 4
VfL_Freak Swing KeyListener, um einen Dialog per ESC zu schließen AWT, Swing, JavaFX & SWT 6
A Keylistener reagiert nicht AWT, Swing, JavaFX & SWT 10
D Problem mit KeyListener AWT, Swing, JavaFX & SWT 2
J KeyListener um auf CTRL-Enter zu reagieren AWT, Swing, JavaFX & SWT 2
L Snake in Java KeyListener Problem AWT, Swing, JavaFX & SWT 30
B "globaler" KeyListener? AWT, Swing, JavaFX & SWT 3
B JTable TableHeader KeyListener AWT, Swing, JavaFX & SWT 4
S Swing KeyListener und JList AWT, Swing, JavaFX & SWT 2
R KeyListener funzt nicht AWT, Swing, JavaFX & SWT 2
X KeyListener AWT, Swing, JavaFX & SWT 4
P KeyListener + Animation AWT, Swing, JavaFX & SWT 2
V Problem mit KeyListener im Fullscreen-Modus AWT, Swing, JavaFX & SWT 2
M AWT KeyListener reagiert nicht AWT, Swing, JavaFX & SWT 10
C Swing KeyListener reagiert nicht AWT, Swing, JavaFX & SWT 7
K JFrame + KeyListener + Runnable = Fehler AWT, Swing, JavaFX & SWT 3
F Tastenabfrage (KeyListener) AWT, Swing, JavaFX & SWT 2
D KeyListener Problem bei JPanel wechsel AWT, Swing, JavaFX & SWT 2
S Swing JTree mit KeyListener AWT, Swing, JavaFX & SWT 2
L AWT KeyListener, requestFocus und KeyBindings AWT, Swing, JavaFX & SWT 8
E JFrame akzeptiert den KeyListener nicht AWT, Swing, JavaFX & SWT 3
F Swing Problem mit KeyListener||paintComponent() in JFrame AWT, Swing, JavaFX & SWT 12
P Swing KeyListener hört nur manchmal zu AWT, Swing, JavaFX & SWT 2
Screen Focus Problem , KeyListener, TextField , Key AWT, Swing, JavaFX & SWT 4
earlgrey_tea AWT KeyListener bekommt keine Signale AWT, Swing, JavaFX & SWT 3
L Problem mit KeyListener AWT, Swing, JavaFX & SWT 3
A KeyListener funktioniert nicht AWT, Swing, JavaFX & SWT 4
D KeyListener-Problem nach dem "Gedrückthalten" einer Taste AWT, Swing, JavaFX & SWT 10
B Swing Keylistener fuer Dialog-Buttons AWT, Swing, JavaFX & SWT 2
B KeyListener Strg+s AWT, Swing, JavaFX & SWT 5
D Globaler Keylistener AWT, Swing, JavaFX & SWT 4
M problem mit keylistener/textarea AWT, Swing, JavaFX & SWT 6
M KeyListener Problem unter Firefox AWT, Swing, JavaFX & SWT 2
L AWT KeyListener, Taste gedrückt halten AWT, Swing, JavaFX & SWT 12
M Komisches Verhalten: JCombobox mit KeyListener AWT, Swing, JavaFX & SWT 13
capgeti SWT KeyListener 2 Tasten Problem AWT, Swing, JavaFX & SWT 3
R KeyListener - welcher Komponente hinzufügen AWT, Swing, JavaFX & SWT 5
Developer_X AWT KeyListener wird nicht ausgeführt! AWT, Swing, JavaFX & SWT 3
N JFrame und KeyListener AWT, Swing, JavaFX & SWT 6
M KeyListener reagiert nach Buttondruck nicht mehr AWT, Swing, JavaFX & SWT 4
A AWT Button verhindert ausführung vom Keylistener AWT, Swing, JavaFX & SWT 4
R KeyListener hinzufügen AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben