# JFrame mit JInternalFrames, Keylistener-Problem



## GianaSisters (9. Sep 2014)

Hallo Zusammen,

wie in der Überschrift beschrieben habe ich ein Problem mit meinem KeyListener im JFrame.
Ich möchte mit F1 ein Hilfefenster öffnen - das funktioniert auch soweit.

```
frame.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println("DRÜC");
				if (e.getKeyCode() == KeyEvent.VK_F1){
            		JavaHelper jh = new JavaHelper();
            		jh.createHelper("hauptmaske");
            	}
			}
		});
```

Sobald ich aber ein neues JInternalframe innerhalb des JFrames öffne funktioniert der KeyListener nicht mehr. Ich müßte also, sobald ein JIF wieder geschlossen ist den Focus auf das Hauptframe bekommen
Für das Internalframe habe ich auch einen Listener benutzt der das schliessen auch wieder erkennt. Die Frage ist halt, wie kann ich wieder auf den Status kommen, dass dann der KeyListener wieder funktioniert? Vielen dank schonmal für die Hilfe, 
Giana Sisters


```
frame.getContentPane().add(rez);
					rez.addInternalFrameListener(new InternalFrameListener() {

						@Override
						public void internalFrameActivated(
								InternalFrameEvent arg0) {
							// TODO Auto-generated method stub
							
						}
@Override
						public void internalFrameClosed(
								InternalFrameEvent arg0) {
							// TODO Auto-generated method stub
							System.out.println("DA isser");
							
						}
```


----------



## Lodoss (9. Sep 2014)

Ich würde vorschlagen, das du dir einen globalen Eventlistener erstellst, der dann ermittelt, für wen das event nun eigentlich gilt.
-> Wenn ein InternalFrame (focus hat/aktiv ist) und nicht geschlossen ist, dann ist dieser gemeint
-> wenn kein InternalFrame gemeint ist, dann ist das Hauptfenster gemeint

ich habe dir da mal eine Demo gebaut (Hilfe ist auf STRG+H, kann in der var SHORTCUT_HELP geändert werden):


```
package globalFocusDemo;

import java.awt.AWTEvent;
import java.awt.AWTKeyStroke;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.KeyStroke;

public class GlobalFocusDemo
{
	JDesktopPane desktop;
	
	public static final AWTKeyStroke SHORTCUT_HELP = KeyStroke.getAWTKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK);
	
	public GlobalFocusDemo()
	{
		// create main frame with desktop-pane
		JFrame mainFrame = new JFrame();
		mainFrame.setSize(800,600);
		
		desktop = new JDesktopPane();
		mainFrame.setContentPane(desktop);
		
		// create some internal-frames
		createFrame("first");
		createFrame("second");
		
		// register global event listener, which only process the KeyEvent SHORTCUT_HELP
		Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener()
		{
		    public void eventDispatched(AWTEvent e)
		    {
		    	// only handle key events
		    	if (!(e instanceof KeyEvent))
		    	{
		    		return;
		    	}
		    	
		    	// if the pressed key match our shortcut...
	    		if (KeyStroke.getAWTKeyStrokeForEvent((KeyEvent)e) == SHORTCUT_HELP)
	    		{
	    			// check if one of the internal-frames has...
	    			for (Component comp : desktop.getComponents())
	    			{
	    				// (only handle internal-frames)
	    				if (!(comp instanceof JInternalFrame))
	    				{
	    					continue;
	    				}
	    				JInternalFrame win = (JInternalFrame)comp;
	    				
	    				// ... focus/isActive and is not closed
	    				if ((win.hasFocus() || win.isSelected()) && !win.isClosed())
	    				{
	    					// print title of that window
	    					System.out.println("Internal window " + win.getTitle() + " has focus");
	    					// TODO: add HELP action for child window (win)
	    					return;
	    				}
	    			}
	    			// okey, no child has focus, main window has been targeted
	    			System.out.println("main window has focus");
	    			// TODO: add HELP action for main window (mainframe/desktop)
	    		}
		    }
		}, AWTEvent.KEY_EVENT_MASK);
		
		mainFrame.setVisible(true);
	}
	
	private void createFrame(String windowName)
	{
		JInternalFrame frame = new JInternalFrame();
	    frame.setTitle(windowName);
	    frame.setSize(300,300);
	    frame.setVisible(true);
	    frame.setClosable(true);
	    desktop.add(frame);
	}
	
	public static void main(String[] args)
	{
		new GlobalFocusDemo();
	}
}
```


----------



## GianaSisters (10. Sep 2014)

Danke Lodoss,
dein Beispiel hat bei mir leider nicht funktioniert, allerdings dann in meinem Programm dann doch wunderbar. Spitze!


----------



## GianaSisters (10. Sep 2014)

Zu früh gefreut, das selbe Problem besteht weiterhin. Schließe ich ein JInternalFrame funktioniert der AWTEventListener gar nicht mehr. Ich kann auf dem Frame bzw Desktop rumklicken wie ich will und dann den Shortcut drücke passiert nichts (also der AWTEL wird nicht ausgeführt). Wenn ich allerdings das Fenster minimiere und dann wieder gross mache klappt es wieder. Irgendein Focusproblem muss da bestehen 

Also zusammengefasst die Frage:
Nach dem Schließen eines JInternalFrame funktioniert dies nicht mehr in der Klasse MainFrame vom typen JFrame:

```
if (KeyStroke.getAWTKeyStrokeForEvent((KeyEvent)e) == SHORTCUT_HELP)
	    		{
	    			System.out.println(desk.getComponent(0).getClass());
	    			if (!(desk.getComponent(0) instanceof JInternalFrame)){
	    				// MainMenu Hilfe anzeigen
	    				JavaHelper jh = new JavaHelper();
	    				jh.createHelper("hauptmaske");
	    			}

	    		}
 
}, AWTEvent.KEY_EVENT_MASK);
```


----------



## jgh (10. Sep 2014)

> enn ich allerdings das Fenster minimiere und dann wieder gross mache klappt es wieder. Irgendein Focusproblem muss da bestehen


hast du nach dem Schließen des InternalFrame mal ein validate(), oder revalidate() auf das Hauptfenster aufgerufen? Eigentlich sind die Methoden imho für etwas anderes da, aber wenn du nach einem mini- und maximieren des Fensters die gewünschte Funktionalität hast...Versuch macht klug.


----------



## GianaSisters (10. Sep 2014)

klappt leider auch nicht, ich mache das schliessen eines InternalFrames über den InternalFrameListener mit der Methode internalFrameClosed


----------



## jgh (10. Sep 2014)

dachte das hat geklappt  schade!
Ein KSKB das das Verhalten nachstellen kann, hast du wahrscheinlich nicht parat?


----------



## GianaSisters (10. Sep 2014)

Hallo jgh,
nun habe ich gerade ein kleines Programm gebastelt, was genau den selben Effekt hat.
Zum testen... Programm starten: 
1) Alt+F1 drücken -> System.out.println wird ausgegeben
2) Öffnen drücken -> Internalframe geht auf -> Alt+F1 geht weiterhin mit ausgabe
3.) Das InternalFrame über das X oben rechts schließen und wieder Alt+F1 drücken -> NIX PASSIERT
4.) Das Leere Frame verkleinern und wieder groß machen -> Alt+F1 funktioniert wieder...
Also das selbe Problem wie in meinem "richtigen" Programm... Hier der Code:

Klasse 1: Starter

```
import java.awt.AWTEvent;
import java.awt.AWTKeyStroke;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.border.EmptyBorder;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;

public class Starter extends JFrame {

	private JPanel contentPane;
	public static final AWTKeyStroke SHORTCUT_HELP = KeyStroke.getKeyStroke(KeyEvent.VK_F1, InputEvent.ALT_MASK);

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Starter frame = new Starter();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Starter() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
			public void eventDispatched(AWTEvent e) {
				if (!(e instanceof KeyEvent)) {
					return;
				}
				// if the pressed key match our shortcut...
	    		if (KeyStroke.getAWTKeyStrokeForEvent((KeyEvent)e) == SHORTCUT_HELP)
	    		{
	    			System.out.println(getComponent(0).getClass());
	    			if (!(getComponent(0) instanceof JInternalFrame)){

	    				System.out.println("normal");
	    			}
    		
	    		}
			}


		}, AWTEvent.KEY_EVENT_MASK);
		
		JButton btnffnen = new JButton("\u00D6ffnen");
		btnffnen.setBounds(10, 11, 89, 23);
		contentPane.add(btnffnen);
		btnffnen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				InternalFrameTest eff = new InternalFrameTest();
				getContentPane().add(eff);
				eff.setFocusable(true);
				eff.show();
				eff.requestFocus();
				eff.addInternalFrameListener(new InternalFrameListener() {

					@Override
					public void internalFrameActivated(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void internalFrameClosed(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void internalFrameClosing(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void internalFrameDeactivated(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void internalFrameDeiconified(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void internalFrameIconified(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void internalFrameOpened(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub
						
					}
					
				});
			}
		});
	}
}
```

Klasse 2: InternalFrameTest

```
import java.awt.EventQueue;

import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;

public class InternalFrameTest extends JInternalFrame {

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					InternalFrameTest frame = new InternalFrameTest();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public InternalFrameTest() {
		setBounds(100, 100, 450, 300);
		setClosable(true);
		getContentPane().setLayout(null);
		
		final JDesktopPane desktopPane = new JDesktopPane();
		desktopPane.setBounds(39, 259, 1, 1);
		getContentPane().add(desktopPane);
		
	}
}
```


----------



## jgh (11. Sep 2014)

danke für das KSKB...nächstes Mal bitte nur eine Datei und eine Main-Methode  
egal, dein Problem ist -wie du schon vermutet hattest- dass dein Frame den Focus verliert: Also ein einfaches 
	
	
	
	





```
requestFocus()
```
hilft!
Ich habe es hier nur in der internalFrameClosed Methode implementiert...evtl. noch anpassen.
Und du brauchst halt noch eine Referenz auf deinen Frame, die ich hier unschön -aber praktikabel- in der main-method setze.


```
import java.awt.AWTEvent;
import java.awt.AWTKeyStroke;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.border.EmptyBorder;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;

class Starter extends JFrame {

	private JPanel contentPane;
	public static final AWTKeyStroke SHORTCUT_HELP = KeyStroke.getKeyStroke(
			KeyEvent.VK_F1, InputEvent.ALT_MASK);

	/**
	 * Launch the application.
	 */

	private static JFrame f;

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Starter frame = new Starter();
					f = frame;
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Starter() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
			public void eventDispatched(AWTEvent e) {
				if (!(e instanceof KeyEvent)) {
					return;
				}
				System.out.println(((KeyEvent) e));
				if (KeyStroke.getAWTKeyStrokeForEvent((KeyEvent) e) == SHORTCUT_HELP) {
					System.out.println(getComponent(0).getClass());
					if (!(getComponent(0) instanceof JInternalFrame)) {

						System.out.println("normal");
					}

				}
			}

		}, AWTEvent.KEY_EVENT_MASK);

		JButton btnffnen = new JButton("\u00D6ffnen");
		btnffnen.setBounds(10, 11, 89, 23);
		contentPane.add(btnffnen);
		btnffnen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				InternalFrameTest eff = new InternalFrameTest();
				getContentPane().add(eff);
				eff.setFocusable(true);
				eff.show();
				eff.requestFocus();
				eff.addInternalFrameListener(new InternalFrameListener() {

					@Override
					public void internalFrameActivated(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void internalFrameClosed(InternalFrameEvent arg0) {

						f.requestFocus();

					}

					@Override
					public void internalFrameClosing(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void internalFrameDeactivated(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void internalFrameDeiconified(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void internalFrameIconified(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void internalFrameOpened(InternalFrameEvent arg0) {
						// TODO Auto-generated method stub

					}

				});
			}
		});
	}
}

class InternalFrameTest extends JInternalFrame {

	/**
	 * Create the frame.
	 */
	public InternalFrameTest() {
		setBounds(100, 100, 450, 300);
		setClosable(true);
		getContentPane().setLayout(null);

		final JDesktopPane desktopPane = new JDesktopPane();
		desktopPane.setBounds(39, 259, 1, 1);
		getContentPane().add(desktopPane);

	}
}
```


----------



## GianaSisters (11. Sep 2014)

So, super vielen Dank. Jetzt klappt's aber wirklich! Dabei ist es doch so einfach, dachte aber, es schonmal so versucht zu haben aber nun geht's!


----------

