KeyListener responder por JFrame
-
08-07-2019 - |
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?
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.