Pergunta

Eu estou tentando implementar um KeyListener para o meu JFrame. No construtor, estou usando este código:

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 eu executá-lo, a mensagem test surge no meu console. No entanto, quando eu pressionar uma tecla, eu não receber qualquer uma das outras mensagens, como se o KeyListener nem estava lá.

Eu estava pensando que poderia ser porque o foco não está no JFrame
e assim eles KeyListener não receber quaisquer eventos. Mas, eu tenho certeza que é.

Existe algo que eu estou ausente?

Foi útil?

Solução

Você deve adicionar o seu KeyListener para todos os componentes que você precisa. Somente o componente com o foco irá enviar esses eventos. Por exemplo, se você tem apenas uma caixa de texto em seu JFrame, que TextBox tem o foco. Portanto, você deve adicionar um KeyListener a este componente também.

O processo é o mesmo:

myComponent.addKeyListener(new KeyListener ...);

Nota: Alguns componentes não são focusable como JLabel

.

Para configurá-los para focalizável você precisa:

myComponent.setFocusable(true);

Outras dicas

Se você não quiser registrar um ouvinte em cada componente,
você poderia adicionar seu próprio KeyEventDispatcher para o 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 foram projetados para capturar os principais eventos para o componente, ele e todos os seus sub-componentes, ou toda a janela. Isto é controlado através do parâmetro em JComponent.getInputMap (). Consulte como usar Key Bindings para documentação.

A beleza deste projeto é que se pode escolher quais traços essenciais são importantes para monitorar e ter ações diferentes disparou com base nesses cursos chaves.

Este código irá chamar dispose () em um JFrame quando a chave de escape é atingido em qualquer lugar na janela. JFrame não deriva de JComponent então você tem que usar outro componente no JFrame para criar a chave de ligação. O painel de conteúdo pode ser um componente.

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 é baixo nível e aplica-se apenas a um único componente. Apesar das tentativas de torná-lo mais utilizável JFrame cria uma série de componentes de componentes, sendo o mais óbvio do painel de conteúdo. JComboBox UI é também frequentemente implementadas de forma similar.

É importante notar a eventos do mouse o trabalho de uma forma estranha um pouco diferente para os principais eventos.

Para obter detalhes sobre o que deve fazer, ver a minha resposta sobre atalho -. java swing

Eu tenho o mesmo problema até que eu li que o problema real é sobre o foco do seu JFrame já adicionou Ouvintes mas excursão quadro não está em foco porque você tem um monte de componentes internos do JFrame que também são focalizável de modo a tentar:

JFrame.setFocusable(true);

Good Luck

Deion (e qualquer outra pessoa fazer uma pergunta similar), você pode usar o código de Pedro acima, mas em vez de imprimir para a saída padrão, você testar o código de tecla pressionada, liberado, ou digitado.

@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;
}

a fim de capturar os principais eventos de campos de texto tudo em um JFrame , pode-se empregar um processador chave evento post. Aqui está um exemplo de trabalho, depois de adicionar o óbvio inclui.

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 .. que classe é o seu construtor para? Provavelmente alguma classe estendendo JFrame? O foco da janela deve estar na janela, é claro, mas eu não acho que esse é o problema.

Eu expandiu seu código, tentou executá-lo e funcionou - as teclas pressionadas resultou como saída de impressão. (Correr com Ubuntu através 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);
    }
}

Isso deve ajudar

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

Eu tenho tido o mesmo problema. Segui o conselho de Bruno para você e descobriram que a adição de um KeyListener apenas para o botão "primeiro" no JFrame (ou seja, na parte superior esquerda) fez o truque. Mas eu concordo com você que é uma espécie de solução inquietante. Então eu brincava ao redor e descobriu uma maneira mais limpa para corrigi-lo. Basta adicionar a linha

myChildOfJFrame.requestFocusInWindow();

para o seu método principal, depois de ter criado sua instância de sua subclasse de JFrame e configurá-lo visível.

lol .... tudo que você tem a fazer é se certificar de que

addKeyListener (this);

é colocado corretamente no seu código.

Você poderia ter JComponents personalizados definiu seu focalizável JFrame pai.

Basta adicionar um construtor e passar o JFrame. Em seguida, fazer uma chamada para setFocusable () in paintComponent.

Desta forma, o JFrame receberá sempre KeyEvents independentemente de outros componentes são pressionadas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top