# Probleme mit JPanel!KeyListener geht nicht



## Robokopp (22. Mrz 2012)

Hallo,

ich hab ein kleines Spiel angefangen, welches sich in etwa an IcyTower orientiert. Dazu hab ich eine MainKlasse, die JPanel erweitert.Der Aufbau ist ähnlich zu dem Tutorial hier im Forum, wo man den Heli steuern kann.D.h. die Klasse Sprite ist vorhanden, und das zeichnen der Objekte funktioniert im Prinzip genauso.

Nun hab ich eine weitere Klasse SideBar erstellt, die einen Seitenbereich erstellen soll, in dem dann bspw. die Score etc gezeichnet werden soll.


```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;


public class SideBar extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private BufferedImage clock;
	private BufferedImage sidebarbackground;
	public SideBar(){
		JPanel panel = new JPanel();
		panel.setVisible(true);
		panel.add(this);
		try {
			clock=ImageIO.read(new File("Sources/clock.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			sidebarbackground=ImageIO.read(new File("Sources/sidebarbackground.jpg"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	public void paintComponent(Graphics g){
		g.drawImage(sidebarbackground, 0, 0,this.getWidth(),this.getHeight(), null);
		g.drawImage(clock, 30, 80,180,180, null);
		

	}
}
```

nun das verrückte:

sobald ich dem JFrame das Panel mit .add("East",sidebar) hinzufüge, funktionieren die Steuertasten im Spiel nicht mehr. Ich kann keine Aktionen ausführen.Alles wird korrekt angezeigt und Fehler gibt es auch nicht...

Meine Vermutung war, dass der KeyListener irgendwie überdeckt wird(?!?) so dass die Keyactions an die Sidebar weitergeleitet werden, anstatt an das Gamepanel.

Kann mir da jemand helfen?
wenn es nötig ist poste ich noch den Konstruktor der MainKlasse, aber der ist ja eh meistens annähernd gleich bei der Art von Projekten


----------



## Marco13 (23. Mrz 2012)

Überdeckt wohl nicht, ist wohl eher ein Fokusproblem: Wenn der Fokus auf dem Slider ist, kann man desses Knopf z.B. mit den Pfeiltasten bewegen - aber auf dem Panel kommt nichts mehr an. 

Das Panel selbst müßte wohl auch mit
panel.setFocusable(true);
fokussierbar gemacht werden. Dann sollte der KeyListener immer funktionieren, WENN man z.B. vorher mal in das Panel geklickt hat. 

Abhilfen für den generellen Fall: Entweder ein FocusListener und sowas wie "requestFocusInWindow" auf dem Panel aufrufen, aber das ist heikel... Alternative könten How to Use Key Bindings (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features) sein


----------



## Robokopp (23. Mrz 2012)

Okay danke, werde ich dann mal probieren. Aber ich verstehe nicht wo der Fokus hin sein soll. Ich hab keine slider und im anderen jpanel kommt auch nichts an.wenn ich das jpanel jedoch direkt in der Mainklasse erzeuge, funktioniert es.

Gesendet von meinem GT-I9100 mit Tapatalk


----------



## Marco13 (23. Mrz 2012)

Ach ... Sidebar ... nicht Slider ... DAS war wohl EINDEUTIG zu spät gestern 

Aber auch jetzt sieht der Code seltsam aus: Dort wird ein Panel erstellt, und die Sidebar wird zu diesem Panel hinzugefügt, aber ... das dort erstellte Panel hängt ja in der Luft...???:L


----------



## Robokopp (23. Mrz 2012)

Achso das erklärt einiges

ne es hängt nicht in der Luft(siehe Anhang)^^
ich definiere die größe und Location in der Mainklasse 

ahh danke, das mit dem Fokus war des rätsels lösung


----------



## Marco13 (23. Mrz 2012)

Das kann aber nur die vom Sidebar-Panel sein - an das andere kommt man ja nicht mehr dran

```
public SideBar(){
        JPanel panel = new JPanel();  // Erstelle ein neues Panel
        panel.setVisible(true); // Überflüssig, BTW...
        panel.add(this); // Füge die Sidebar zum neu erzeugten Panel hinzu

        ...
        // Mache hier NICHTS mehr mit dem neuen Panel,
        // und gib es NICHT nach draußen...
    }
```
Dieses Panel erfüllt keinen Zweck.

Hat aber nicht unbedingt mit dem Problem zu tun. 

Ein Beispiel, was ich meinte: Hier wird ein KeyListener ans "Center"-Panel gehängt (das dazu Focusable sein muss!), und der reagiert auf Tastendrücke. Wenn man aber einmal den Button klickt, reagiert das Center-Penl erstmal nicht mehr, weil es den Fokus verliert.

```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class PanelTest
{
	public static void main(String[] args)
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				createAndShowGUI();
			}
		});
	}
	
	private static void createAndShowGUI()
	{
		JFrame f = new JFrame();
		f.getContentPane().setLayout(new BorderLayout());
		
		JPanel center = new JPanel();
		center.add(new JLabel("Center"));
		center.setFocusable(true);
		
		// Wenn die Maus im Center gedrückt wird, 
		// fordere den Fokus an
		center.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mousePressed(MouseEvent e)
			{
				e.getComponent().requestFocusInWindow();
			}
			@Override
			public void mouseEntered(MouseEvent e)
			{
				e.getComponent().requestFocusInWindow();
			}
		});
		center.setBackground(Color.GREEN);
		center.addKeyListener(createKeyListener("Center"));
		
		// Gib informationen darüber aus, wenn das 
		// Center den Fokus verliert
		center.addFocusListener(new FocusListener()
		{
			@Override
			public void focusLost(FocusEvent e)
			{
				System.out.println("Center LOST Focus to "+e.getOppositeComponent());
			}
			
			@Override
			public void focusGained(FocusEvent e)
			{
				System.out.println("Center GAINED Focus from "+e.getOppositeComponent());
			}
		});
		
		f.getContentPane().add(center, BorderLayout.CENTER);
		
		
		JPanel sideBar = new JPanel();
		sideBar.add(new JLabel("SideBar"));
		sideBar.add(new JButton("Button"));
		sideBar.addKeyListener(createKeyListener("SideBar"));
		sideBar.setBackground(Color.WHITE);
		f.getContentPane().add(sideBar, BorderLayout.EAST);
		
		f.setSize(500,500);
		f.setVisible(true);
	}
	
	private static KeyListener createKeyListener(final String name)
	{
		return new KeyListener()
		{
			@Override
			public void keyTyped(KeyEvent e)
			{
				System.out.println("Event on "+name+": "+e);
			}

			@Override
			public void keyPressed(KeyEvent e)
			{
				System.out.println("Event on "+name+": "+e);
			}

			@Override
			public void keyReleased(KeyEvent e)
			{
				System.out.println("Event on "+name+": "+e);
			}
		};		
	}
	
	
}
```


Mehr Infos gibt's auf How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)


----------



## Robokopp (23. Mrz 2012)

Ja das hab ich am anfang auch irgendwie festgestellt, als ich in der SideBarklasse eine Hintergrundfarbe eingestellt habe und diese ewig nicht übernommen wurde


----------

