Question

J'essaie d'implémenter un KeyListener pour mon JFrame . Sur le constructeur, j'utilise ce code:

System.out.println("test");
addKeyListener(new KeyListener() {
    public void keyPressed(KeyEvent e) { System.out.println( "tester"); }

    public void keyReleased(KeyEvent e) { System.out.println("2test2"); }

    public void keyTyped(KeyEvent e) { System.out.println("3test3"); }
});

Lorsque je l'exécute, le message test apparaît dans ma console. Cependant, lorsque j'appuie sur une touche, aucun autre message ne s'affiche, comme si KeyListener n'était même pas là.

Je pensais que cela pourrait être parce que l'accent n'est pas mis sur le JFrame
et donc ils KeyListener ne reçoivent aucun événement. Mais je suis presque sûr que ce l'est.

Y a-t-il quelque chose qui me manque?

Était-ce utile?

La solution

Vous devez ajouter votre keyListener à chaque composant dont vous avez besoin. Seul le composant avec le focus enverra ces événements. Par exemple, si vous n'avez qu'une seule zone de texte dans votre JFrame, cette zone a le focus. Vous devez donc également ajouter un KeyListener à ce composant.

Le processus est le même:

myComponent.addKeyListener(new KeyListener ...);

Remarque: certains composants ne peuvent pas être mis au point, comme JLabel.

Pour les définir sur focusable, vous devez:

myComponent.setFocusable(true);

Autres conseils

Si vous ne souhaitez pas enregistrer un écouteur sur chaque composant,
vous pouvez ajouter votre propre KeyEventDispatcher au KeyboardFocusManager :

public class MyFrame extends JFrame {    
    private class MyDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_PRESSED) {
                System.out.println("tester");
            } else if (e.getID() == KeyEvent.KEY_RELEASED) {
                System.out.println("2test2");
            } else if (e.getID() == KeyEvent.KEY_TYPED) {
                System.out.println("3test3");
            }
            return false;
        }
    }
    public MyFrame() {
        add(new JTextField());
        System.out.println("test");
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher());
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

InputMaps et ActionMaps ont été conçus pour capturer les événements clés du composant, de celui-ci et de tous ses sous-composants, ou de la fenêtre entière. Ceci est contrôlé par le paramètre JComponent.getInputMap (). Consultez la utilisation des raccourcis-clés pour la documentation.

La beauté de cette conception réside dans le fait qu’il est possible de choisir les touches importantes à surveiller et de déclencher différentes actions en fonction de ces touches.

Ce code appellera la disposition () sur une image JFrame lorsque la touche d'échappement est enfoncée n'importe où dans la fenêtre. JFrame ne dérive pas de JComponent, vous devez donc utiliser un autre composant dans JFrame pour créer la liaison de clé. Le volet de contenu peut être un tel composant.

InputMap inputMap; 
ActionMap actionMap;
AbstractAction action;
JComponent component;

inputMap  = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
actionMap = component.getActionMap();

action    = new AbstractAction()
{
   @Override
   public void actionPerformed(ActionEvent e)
   {
      dispose();
   }
};

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose");
actionMap.put("dispose", action);

KeyListener est de bas niveau et ne s'applique qu'à un seul composant. Malgré les tentatives visant à le rendre plus utilisable, JFrame crée un certain nombre de composants, le plus évident étant le volet contenu. JComboBox L’UI est également souvent implémentée de la même manière.

Il est à noter que les événements de la souris fonctionnent d'une manière étrange, légèrement différente de celle des événements clés.

Pour plus d'informations sur ce que vous devez faire, voir ma réponse à la page raccourci - Java Swing .

J’ai eu le même problème jusqu’à ce que j’ai lu que le vrai problème est FOCUS, votre JFrame a déjà ajouté des auditeurs, mais le cadre de la tournée n’est jamais sur Focus car vous avez dans votre JFrame un grand nombre de composants qui peuvent également être mis au point. Essayez:

JFrame.setFocusable(true);

Bonne chance

Deion (et toute autre personne posant une question similaire), vous pouvez utiliser le code de Peter ci-dessus, mais au lieu d’imprimer sur une sortie standard, vous testez le code de clé PRESSED, RELEASED ou TYPED.

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getID() == KeyEvent.KEY_PRESSED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_RELEASED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_TYPED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    }
    return false;
}

afin de capturer les événements clés de TOUS les champs de texte dans un JFrame , on peut employer un post-processeur d’événement clé. Voici un exemple de travail, après avoir ajouté l'évidence incluse.

public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor {
    public static final long serialVersionUID = 1L;

    public KeyListenerF1Demo() {
        setTitle(getClass().getName());

        // Define two labels and two text fields all in a row.
        setLayout(new FlowLayout());

        JLabel label1 = new JLabel("Text1");
        label1.setName("Label1");
        add(label1);

        JTextField text1 = new JTextField(10);
        text1.setName("Text1");
        add(text1);

        JLabel label2 = new JLabel("Text2");
        label2.setName("Label2");
        add(label2);

        JTextField text2 = new JTextField(10);
        text2.setName("Text2");
        add(text2);

        // Register a key event post processor.
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventPostProcessor(this);
    }

    public static void main(String[] args) {
        JFrame f = new KeyListenerF1Demo();
        f.setName("MyFrame");
        f.pack();
        f.setVisible(true);
    }

    @Override
    public boolean postProcessKeyEvent(KeyEvent ke) {
        // Check for function key F1 pressed.
        if (ke.getID() == KeyEvent.KEY_PRESSED
                && ke.getKeyCode() == KeyEvent.VK_F1) {

            // Get top level ancestor of focused element.
            Component c = ke.getComponent();
            while (null != c.getParent())
                c = c.getParent();

            // Output some help.
            System.out.println("Help for " + c.getName() + "."
                    + ke.getComponent().getName());

            // Tell keyboard focus manager that event has been fully handled.
            return true;
        }

        // Let keyboard focus manager handle the event further.
        return false;
    }
}

Hmm .. à quelle classe s'adresse votre constructeur? Probablement une classe qui étend JFrame? La fenêtre doit être active, bien sûr, mais je ne pense pas que ce soit le problème.

J'ai développé votre code, essayé de l'exécuter et cela a fonctionné - les pressions sur les touches ont donné lieu à une sortie imprimée. (exécuté avec Ubuntu via Eclipse):

public class MyFrame extends JFrame {
    public MyFrame() {
        System.out.println("test");
        addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                System.out.println("tester");
            }

            public void keyReleased(KeyEvent e) {
                System.out.println("2test2");
            }

            public void keyTyped(KeyEvent e) {
                System.out.println("3test3");
            }
        });
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

Cela devrait aider

    yourJFrame.setFocusable(true);
    yourJFrame.addKeyListener(new java.awt.event.KeyAdapter() {


        @Override
        public void keyTyped(KeyEvent e) {
            System.out.println("you typed a key");
        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("you pressed a key");
        }

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("you released a key");
        }
    });

J'ai eu le même problème. J'ai suivi le conseil de Bruno et constaté que l’ajout d’un KeyListener au "premier" JFrame (en haut à gauche) a fait l'affaire. Mais je suis d'accord avec vous, c'est en quelque sorte une solution déroutante. J'ai donc bricolé et découvert un moyen plus ordonné de le réparer. Ajoutez juste la ligne

myChildOfJFrame.requestFocusInWindow();

à votre méthode principale, après avoir créé votre instance de votre sous-classe de JFrame et l'avoir rendue visible.

lol .... tout ce que vous avez à faire est de vous assurer que

addKeyListener (this);

est placé correctement dans votre code.

Vous pouvez configurer des composants JComponents personnalisés pour qu'ils puissent être focalisés sur leur parent JFrame.

Ajoutez simplement un constructeur et transmettez le JFrame. Appelez ensuite setFocusable () dans paintComponent.

Ainsi, JFrame recevra toujours KeyEvents, que les autres composants soient activés ou non.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top