# KeyListener reagiert nicht



## plammy (3. Jul 2012)

Hallo  Diesmal habe ich kein kleines Testprogramm geschrieben statt mein kompletten komplizieren Code zu posten ... Und bei meinem Programm funktioniert das nicht bei meinem Testprogramm auch nicht.. 
Es geht um KeyListener.. Als erstes will ich dass zumindest iwelchen Text auf der Konsole ausgegeben wird wenn ich z.B. die linke oder rechte Maustaste gedrückt habe... Später sollen Rechtecke mit den Maustasten bewegt werden.. Aber als erstes einfache Ausgabe... So ich das geschriebene habe tut sich nix.. Wird nichts ausgegeben ..


```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication7;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class TestListener extends JPanel{
    
    
    KeyAdapt li = new KeyAdapt();
    
    public TestListener(){
        addKeyListener(li);
    }
    
    class KeyAdapt extends KeyAdapter {
        public void keyPressed(KeyEvent e)
        {
                   
            if(e.getKeyCode() == KeyEvent.VK_LEFT)
            {
                System.out.println("left");    
            
            }
            if(e.getKeyCode() == KeyEvent.VK_RIGHT)
            {
                System.out.println("right");             
            }
        }
    }
    
    public void paintComponent(Graphics g) {  
       super.paintComponent(g); 
       Rectangle r = new Rectangle(20,20,50,50);
       g.fillRect(r.x,r.y,r.width,r.height);
    }
    
    public static void main(String[] args) { 
    JFrame window = new JFrame("Test"); 
    window.setSize(360, 200); 
    window.setLocation(100, 100); 
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    window.getContentPane().add(new TestListener()); 
    window.setVisible(true); 
  } 
}
```


----------



## SlaterB (3. Jul 2012)

hast du je irgendwo ein Programm gesehen, das so funktioniert? 
wie kommen die Leute nur immer darauf, das überhaupt so zu versuchen,
ist mir ein großes Rätsel 

mit

```
TestListener tl = new TestListener();
        window.getContentPane().add(tl); 
        window.setVisible(true); 
        tl.requestFocus();
```
geht es vorerst, 

aber allgemein nicht zu empfehlen,
auch wenn die Alternative KeyBindings auch nicht so direkt schön aussieht

How to Use Key Bindings (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)


----------



## plammy (3. Jul 2012)

Und was ist wenn ich das für eine innere Klasse anwenden will?


```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication7;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class TestListener extends JPanel{
    
    
    KeyAdapt li = new KeyAdapt();
    
    public TestListener(){
        
    }
    
    
    class IntereKlasse {
        
        public IntereKlasse(){
            super();
            addKeyListener(li);
            setFocusable(true); 
            requestFocus();
        }
    }
    class KeyAdapt extends KeyAdapter {
        public void keyPressed(KeyEvent e)
        {
                   
            if(e.getKeyCode() == KeyEvent.VK_LEFT)
            {
                System.out.println("left");    
            
            }
            if(e.getKeyCode() == KeyEvent.VK_RIGHT)
            {
                System.out.println("right");             
            }
        }
    }
    
    public void paintComponent(Graphics g) {  
       super.paintComponent(g); 
       Rectangle r = new Rectangle(20,20,50,50);
       g.fillRect(r.x,r.y,r.width,r.height);
    }
    
    public static void main(String[] args) { 
    TestListener tl = new TestListener();
    JFrame window = new JFrame("Test"); 
    window.setSize(360, 200); 
    window.setLocation(100, 100); 
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    window.getContentPane().add(tl); 
    window.setVisible(true); 
//    tl.requestFocus();
  } 
}
```

so klappts nicht


----------



## so0jvpwemm (3. Jul 2012)

Ich würde mir Slaters Vorschlag mit den KeyBindings zu Herzen nehmen. Mit KeyListener wirst Du in diesem Fall nicht glücklich werden.


----------



## so0jvpwemm (3. Jul 2012)

... abgesehen davon, dass Dein Panel mit dem KeyListener gar nicht im Frame verbaut ist.


----------



## SlaterB (3. Jul 2012)

IntereKlasse ist einfach nur eine innere Klasse, von dem nie ein Objekt erzeugt, ergo nie irgendwo addKeyListener() aufgerufen wird, 
so kann freilich nichts passieren, 

IntereKlasse ist im Moment auch kein JPanel, sehr fraglich im Sinn,
die Aufrufe gehen auf das TestListener-JPanel über

Listener ist übrigens ein eher schlechter Name für JPanel, welches nicht mal selber 
ein Listener-Interface implementiert, was durchaus vorkommt 

----

mein Code hatte schon seinen Grund, auch wenn ich ihn diesmal nicht in Worte fasste,
das requestFocus() muss NACH dem setVisible(true) passieren,

solange der Listener auf das JPanel tl geht, reicht Zeile 65 im Originalzustand,
ganz egal in wieviel Verschachtelungen intern der addKeyListener()-Aufruf erfogt, und ganz egal welche Subklasse den Listener darstellt,
das JPanel, auf dem gehört wird, ist wichtig


----------



## plammy (3. Jul 2012)

was mich noch interessieren würde ist , warum funktionieren dann die MouseListners in inneren Klassen??


----------



## plammy (3. Jul 2012)

außerdem muss ich das in der inneren Klasse machen . ich will methoden und variablen darin benutzen die sich in der innere Klasse nur befinden.


----------



## SlaterB (3. Jul 2012)

mit inneren Klassen oder nicht hat das nichts zu tun,

grundsätzlich besteht ein Unterschied, dass die Mausereignisse immer problemlos an genau die Komponente unter der Maus
weitergereicht werden (edit: bzw. bei gedrückter Maustaste an die vom Klick), 
da besteht ein einfacher eindeutiger 'örtlicher' Zusammenhang,

wohin ein Tastendruck an die vielleicht 20 offenen Fenster auf den Desktop oder selbst mehrere Komponenten in einem JFrame 
gehen soll ist nicht ganz so einfach, dafür kommt der Focus hinein,

KeyListener, das kann man sich merken, ist nur wirklich leicht und eindeutig, wenn irgendwo ein Cursor blickt, JTextField & Co.
(was auch den Focus beinhaltet), sonst lieber KeyBindings

> außerdem muss ich das in der inneren Klasse machen

ist wie gesagt kein Teil des Problems, wenn man es richtig macht,
falls du da Probleme hast, so benenne sie auch..,
das bisherige dürfte ausreichend weggefegt worden sein


----------



## plammy (3. Jul 2012)

hmm.. ich glaube da komme ich echt weiter nur mit KeyBinding..





> You're creating a custom component and want to support keyboard access to it.
> For example, you might want the component to react when it has the focus and the user presses the Space key.



Genau das will ich.. ich will ja ein selectiertes Rechteck später mit der Pfeiltasten bewegen können.


----------



## plammy (3. Jul 2012)

ne also es kann nicht sein dass es nicht einfacher geht... in meinem testprogramm wo 60 zeilen und 1 panel ist ok hat geklappt dass man text auf der konsole ausgibt.. Aber.. erstmal ist mein ziel dass wenn man ein bestimmten rechteck selektiert hat DEn dann mit den taustasten bewegen kann... Es kann nicht sein, dass dman dafür iwelche Panel focusieren soll und soweiter.. Gibt es nicht iwelche Variante den rechteck zu selektieren (focusieren ) und dann zu bewegen mit Pfeiltasten?? wenn ich das versuche auf dem rechteck anweden geht das nicht weil der immer ein Component haben will und kein Rechteck:



```
package javaapplication7;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;


public class TestProgramm extends JPanel{

    EditPanel editPanel;
    
    public TestProgramm(){
        editPanel = new EditPanel();
        editPanel.setLayout(null);
        editPanel.setFocusable(true);
     
        editPanel.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "actionName");
        editPanel.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "actionName");
        editPanel.getInputMap().put(KeyStroke.getKeyStroke("UP"), "actionName");
        editPanel.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "actionName");
        
        editPanel.getActionMap().put("actionName", new AbstractAction("actionName") 
        {
            public void actionPerformed(ActionEvent evt) {
                System.out.println(evt);
                repaint();
            }
        });
        
        
       add(editPanel);
    
    }
    
    class EditPanel extends JPanel{
        
        public EditPanel(){
            super();
        }
        
        
        public void paintComponent(Graphics g) {  
            super.paintComponent(g); 
            Rectangle r = new Rectangle(20,20,50,50);
            g.fillRect(r.x,r.y,r.width,r.height);
        }
        
     }
    public static void main(String[] args) { 
        TestProgramm tl = new TestProgramm();

        JFrame window = new JFrame("Test"); 
        window.setSize(360, 200); 
        window.setLocation(100, 100); 
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        window.getContentPane().add(tl); 
        window.setVisible(true); 

  } 
}
```


----------



## SlaterB (3. Jul 2012)

wenn du die Swing-Mechanismen nutzen willst, dann brauchst du auch eine richtige JComponent, die ein Rectangle darstellt,
und in einer größeren Fläche positioniert wird, dann geht auch ein Mausklick an dieses 'Rechteck-Komponente'

ein einfaches Rectangle für paintComponent ist aber praktisch nicht existent, da gibt es keine magischen Verknüpfungen,
für Swing sieht es nur so aus, dass es ein JPanel gibt, an welches die Keys (und auch die Maus!) gehen,
auf dem zufällig irgendwelche Pixel irgendeine Farbe haben,

wie das wann warum gezeichnet wurde, welche Instanzattribute dafür mal genutzt wurden und vielleicht noch da sind (oder als temporäre Variablen längst vergangen), das kann Swing unmöglich wissen/ interpretieren,

du selber kannst aber vieles programmieren was du möchtest, etwa über die MausListener indivuell merken, 
welches Rectangle als letztes 'angeklickt' wurde, indem du den Mausklick mit der Lage aller Rechtecke vergleichst,
dann kannst du die Tastatureingaben je nach deinem gemerkten Wissen zur Verschiebung eines der Rechtecke nutzen,

all das musst du aber selber programmieren, wenn du mit paintComponent völlig frei die Anzeige bestimmst


----------

