KeyListener auf JFrame reagiert nicht

blz

Bekanntes Mitglied
Hallo,

ich habe ein Programm mit einem JFrame geschrieben, der in einem BorderLayout mehrere verschiedene Komponenten enthält:
Ein Panel mit Buttons, dann eins mit JTextareas usw.

Nun möchte ich dem parent-Frame einen KeyListener hinzufügen, damit z. B. ein neues JPanel an eine bestimmte Stelle gesetzt wird.
Ich nahm an, den Listener müsste ich dem Frame hinzufügen, weil der ja die übergeordnete Instanz ist und diese Tastenkombinationen ja immer funktionieren sollen.
Einen KeyListener hinzuzufügen, ist ja nun kein Hexenwerk. Allerdings funktioniert es nicht.

Gibt es ein Problem dadurch, dass immer eine der enthaltenen Komponenten im Fokus ist (also der Button, die Textarea, ...)?
Oder müsste das generell gehen?
 
ich kenne mich nicht so gut aus, aber ich denke es ist ein Fokus problem
setFocusable(true);
requestFocusInWindow();

das sollte das problem lösen, sofern du dir sicher bist dass du alles andere richtig gemacht hast, weil kein code...
aber ich will wissen, was die anderen dazu sagen...😉
 
Zuletzt bearbeitet:
setFocusable(true); und requestFocusInWindow(); lösen das Problem so lange, wie ich keinen Button gedrückt habe. Danach funktioniert der KeyListener wieder nicht mehr - was mich wohl in der Annahme bestätigt, dass es ein Problem des Fokus ist:
Wenn ein Button geklickt wurde, hat er den Fokus und nicht mehr der JFrame, der den KeyListener hat.

Meine Frage ist also eher generellerer Natur:
wie muss die Architektur aussehen, wenn man eine GUI, hat, die aus verschiedenen Knöpfen, Panels, Textfields etc. besteht, damit es "globale" Tastenkombinationen gibt, die immer funktionieren (Praktisch z. B. sowas wie Strg+S für speichern), auch wenn gerade ein Button gedrückt worden ist, der dann noch den Fokus hat.
 
Danke.
Hier der Code und eine Erklärungen für alle, die darüber stolpern:

Java:
        panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK), "DasWasPassierenSoll");
        panel.getActionMap().put("DasWasPassierenSoll", new AbstractAction() {            
            @Override
            public void actionPerformed(ActionEvent e) {
                // Das, was passieren soll
            }
        });

Das praktische an Keybindings ist, dass man nicht auf die Komponente klicken muss, damit sie den Focus hat, sondern, dass sie unabhängig davon funktionieren.

Man braucht zwei Objekte, die eine Komponente schon mitbringt, eine Input- und eine ActionMap:
Die InputMap bildet die Tastenkombination auf einen Actionnamen ab, die Action map bildet den Actionnamen auf eine tatsächliche Action ab.

Beim Tastendrücken wird dann die InputMap der Komponente durchsucht nach der gedrückten Tastenkombination und es wird der Actionname gefunden.
Dann wird die ActionMap nach dem ActionNamen durchsucht und die zugehörige Action augeführt.

Theoretisch könnte man ja nun auf die Idee kommen und sagen, warum sollte ich nicht gleich die Action in die InputMap schreiben und mir den Umweg mit dem ActionNamen sparen? Dann bräuchte man nur eine Map.
Es scheint aber so, wie es ist, besser, "objektorientierter" zu sein. Wers genauer wissen will, müsste sich selbst mit der Doku auseinandersetzen.
 
Theoretisch könnte man ja nun auf die Idee kommen und sagen, warum sollte ich nicht gleich die Action in die InputMap schreiben und mir den Umweg mit dem ActionNamen sparen?
Zum Beispiel weil eine Action nicht unbedingt mit einem Tastendruck verbunden sein muss.

Actions haben übrigens eine ganz nette Eigenschaft: man kann eine Action im Konstruktor von z. B. Buttons und Menüeinträgen verwenden. Die Action konfiguriert dann das jeweilige Element (Name, Mnemonic, Icon, ...) Der Witz: man keine eine Action enablen/disablen und das wirkt sich dann automatisch auf die jeweiligen Elemente in der erwarteten Weise aus.
 
Schon gut, normalerweise hab ich viel Phantasie (oder schaue lange in meine Kaffeetasse 😀 ), allerdings konnte ich mir das nicht ganz aufdröseln. Danke für die Richtigstellung 😉
 

Zurück
Oben