Domanda

Sto cercando di implementare un KeyListener per il mio JFrame . Sul costruttore, sto usando questo codice:

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"); }
});

Quando lo eseguo, viene visualizzato il messaggio test nella mia console. Tuttavia, quando premo un tasto, non ricevo nessuno degli altri messaggi, come se KeyListener non fosse nemmeno lì.

Stavo pensando che potrebbe essere perché il focus non è sul JFrame
e quindi KeyListener non riceve alcun evento. Ma sono abbastanza sicuro che lo sia.

C'è qualcosa che mi manca?

È stato utile?

Soluzione

Devi aggiungere il tuo KeyListener a ogni componente di cui hai bisogno. Solo il componente con lo stato attivo invierà questi eventi. Ad esempio, se hai un solo TextBox nel tuo JFrame, quel TextBox ha il focus. Quindi è necessario aggiungere un KeyListener anche a questo componente.

Il processo è lo stesso:

myComponent.addKeyListener(new KeyListener ...);

Nota: alcuni componenti non sono focalizzabili come JLabel.

Per impostarli su focalizzabili devi:

myComponent.setFocusable(true);

Altri suggerimenti

Se non si desidera registrare un listener su ogni componente,
potresti aggiungere il tuo KeyEventDispatcher al 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 e ActionMaps sono stati progettati per acquisire gli eventi chiave per il componente, esso e tutti i suoi componenti secondari o l'intera finestra. Questo è controllato tramite il parametro in JComponent.getInputMap (). Vedi Come utilizzare i binding di tasti per la documentazione.

La bellezza di questo design è che si può scegliere quali tratti di tasti sono importanti da monitorare e in cui vengono attivate diverse azioni in base a quei tratti di tasto.

Questo codice chiamerà dispose () su un JFrame quando il tasto Esc viene premuto in qualsiasi punto della finestra. JFrame non deriva da JComponent, quindi è necessario utilizzare un altro componente in JFrame per creare l'associazione delle chiavi. Il riquadro del contenuto potrebbe essere un componente del genere.

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 è di basso livello e si applica solo a un singolo componente. Nonostante i tentativi di renderlo più utilizzabile JFrame crea una serie di componenti componenti, il più ovvio è il riquadro del contenuto. Anche l'interfaccia utente JComboBox è spesso implementata in modo simile.

Vale la pena notare che gli eventi del mouse funzionano in un modo strano leggermente diverso dagli eventi chiave.

Per dettagli su cosa dovresti fare, vedi la mia risposta su Tastiera ampia dell'applicazione scorciatoia - Java Swing .

Ho avuto lo stesso problema fino a quando ho letto che il vero problema riguarda FOCUS, il tuo JFrame ha già aggiunto degli ascoltatori, ma il frame del tour non è mai attivo perché nel tuo JFrame ci sono molti componenti che sono anche focalizzabili, quindi prova:

JFrame.setFocusable(true);

Buona fortuna

Deion (e chiunque altro ponga una domanda simile), potresti usare il codice di Peter sopra ma invece di stampare sullo standard output, testerai il codice chiave PRESSED, RELEASED o 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;
}

per acquisire eventi chiave di TUTTI i campi di testo in un JFrame , si può impiegare un post processore di eventi chiave. Ecco un esempio funzionante, dopo aver aggiunto le inclusioni ovvie.

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 .. a che classe è il tuo costruttore? Probabilmente un po 'di estensione della classe JFrame? Il focus della finestra dovrebbe essere alla finestra, ovviamente, ma non credo che sia questo il problema.

Ho ampliato il tuo codice, ho provato a eseguirlo e ha funzionato: la pressione dei tasti è risultata come output di stampa. (eseguito con Ubuntu tramite 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);
    }
}

Questo dovrebbe aiutare

    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");
        }
    });

Ho avuto lo stesso problema. Ho seguito i consigli di Bruno e ho scoperto che l'aggiunta di un KeyListener solo al "primo" pulsante in JFrame (cioè, in alto a sinistra) ha fatto il trucco. Ma sono d'accordo con te, è una specie di soluzione inquietante. Così ho armeggiato e ho scoperto un modo più semplice per risolverlo. Aggiungi la linea

myChildOfJFrame.requestFocusInWindow();

al metodo principale, dopo aver creato l'istanza della sottoclasse di JFrame e averla resa visibile.

lol .... tutto quello che devi fare è assicurarti che

addKeyListener (this);

è inserito correttamente nel tuo codice.

È possibile che JComponents personalizzati impostino il focus JFrame principale.

Basta aggiungere un costruttore e passare il JFrame. Quindi effettua una chiamata a setFocusable () in paintComponent.

In questo modo JFrame riceverà sempre KeyEvents indipendentemente dal fatto che vengano premuti altri componenti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top