KeyListener, KeyEvents e derivados

Pessoal, estou tentando fazer alguns Eventos para quando pressionar o ENTER ele clica no “principal” botão do form, o problema é: Ao passar pela tela de login (que possui listeners nos TextFields) ele também está clicando no botão principal do próximo FORM (que é o Registrar). Como faço para evitar esse “conflito”, pois os botões LOGIN e REGISTRAR (de diferentes frames) estão sendo clicados! VALEU!!!

public void keyPressed(KeyEvent arg0) {
		if(formLogin.isShowing()){
			if(arg0.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("LOGIN PRESSIONADO");
				formLogin.getButtonLogar().doClick();
			}
			if(arg0.getKeyCode() == KeyEvent.VK_ESCAPE){
				System.exit(0);
			}
		}
		if(formPrincipal.isShowing()){
			if(arg0.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("REGISTRAR PRESSIONADO");
				formPrincipal.getButtonRegistrar().doClick();
			}
		}
	}

Listeners:

formLogin.getButtonLogar().addKeyListener(this);
			formLogin.getTextFieldLogin().addKeyListener(this);
			formLogin.getPasswordFieldSenha().addKeyListener(this);
			formPrincipal.getTextFieldNome().addKeyListener(this);

[quote=JoAuM]Pessoal, estou tentando fazer alguns Eventos para quando pressionar o ENTER ele clica no “principal” botão do form, o problema é: Ao passar pela tela de login (que possui listeners nos TextFields) ele também está clicando no botão principal do próximo FORM (que é o Registrar). Como faço para evitar esse “conflito”, pois os botões LOGIN e REGISTRAR (de diferentes frames) estão sendo clicados! VALEU!!!

public void keyPressed(KeyEvent arg0) {
		if(formLogin.isShowing()){
			if(arg0.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("LOGIN PRESSIONADO");
				formLogin.getButtonLogar().doClick();
			}
			if(arg0.getKeyCode() == KeyEvent.VK_ESCAPE){
				System.exit(0);
			}
		}
		if(formPrincipal.isShowing()){
			if(arg0.getKeyCode() == KeyEvent.VK_ENTER){
				System.out.println("REGISTRAR PRESSIONADO");
				formPrincipal.getButtonRegistrar().doClick();
			}
		}
	}

Listeners:

formLogin.getButtonLogar().addKeyListener(this);
			formLogin.getTextFieldLogin().addKeyListener(this);
			formLogin.getPasswordFieldSenha().addKeyListener(this);
			formPrincipal.getTextFieldNome().addKeyListener(this);

[/quote]
Ao invés de “addKeyListener(this)”, crie listeners separados para cada coisa. Fica bem mais organizado.[code]private KeyListener listenerSair = new KeyAdapter() {
public void keyPressed(KeyEvent arg0) {
if (!formLogin.isShowing() || arg0.getKeyCode() != KeyEvent.VK_ESCAPE) return;
System.exit(0);
}
};

private KeyListener listenerLogin = new KeyAdapter() {
public void keyPressed(KeyEvent arg0) {
if (!formLogin.isShowing() || arg0.getKeyCode() != KeyEvent.VK_ENTER) return;
formLogin.getButtonLogar().doClick();
}
};

private KeyListener listenerRegistrar = new KeyAdapter() {
public void keyPressed(KeyEvent arg0) {
if (!formLogin.isShowing() || arg0.getKeyCode() != KeyEvent.VK_ENTER) return;
formPrincipal.getButtonRegistrar().doClick();
}
};[/code]Listeners: formLogin.getButtonLogar().addKeyListener(listenerLogin); formLogin.getTextFieldLogin().addKeyListener(listenerLogin); formLogin.getPasswordFieldSenha().addKeyListener(listenerLogin); formPrincipal.getTextFieldNome().addKeyListener(listenerRegistrar); formPrincipal.addKeyListener(listenerSair); formLogin.addKeyListener(listenerSair);
Ah, mais uma coisa, evita usar doClick(). Ao invés disso, chame diretamente o método que o clique vai provocar.

Você não precisa sequer dos EventListeners.

Se seu problema é só ter um botão principal para ser clicado com enter, faça, no seu construtor:

getRootPane().setDefaultButton(getButtonLogar());

Faça o mesmo no outro JFrame para o botão de registrar. Com uma única linha de código, esse comando deixará o botão principal com um desenho mais destacado e fará com que seja automativamente acionado no enter.

Já para o ESC, fica muito melhor se você registrar um InputMap e um ActionMap.

[code]
InputMap imap = getContentPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
imap.put(KeyStroke.getKeyStroke(“ESCAPE”), “SairDoPrograma”);

//Mapeamos o botão ESC a ação descrita pela string.
ActionMap amap = getContentPane().getActionMap();

//Mapeia a string para a ação a ser executada.
amap.put(“SairDoPrograma”, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}); [/code]

A vantagem é que você só faz isso uma vez, no seu construtor e não precisa ficar adicionando listeners de componente em componente. O que, além de poupar muito trabalho, deixa o código muito mais fácil de manter.

Victor, eu também faço do jeito que vc falou: crio um listener para cada botão, ou tecla. Mas para o caso dos métodos idênticos é uma boa criar uma função separada e fazer todos os métodos chama-la. Assim você evita duplicação de código e torna o programa mais fácil de manter.

Boa tarde novamente!
Utilizei um pouco a idéia de cada um… Quando for default no Form eu uso o getRoot… Já o meu Form principal eu possuo dois scrollPanes dentro de uma tabbedPane ou seja, não posso ter um default naquele form pois quando estou no scroll de consulta, quero que o default seja o botão pesquisa, já quando o scroll for Cadastro quero que o botão seja Registrar mas esse código não funciona assim:

formPrincipal.getScrollPane1().getRootPane().setDefaultButton(formPrincipal.getButtonRegistrar()); formPrincipal.getScrollPane2().getRootPane().setDefaultButton(formPrincipal.getButtonConsultaPesquisa());

Alguma sugestão? E obrigado pela ajuda anterior, embora os InputMaps eu não tenha conseguido usar, usei o RootPane mesmo, e para tecla ESC usei a primeira sugestão… Vou continuar tentando!
Valeu!

Qual foi o problema com os InputMaps?

Não dependa de listeners para o ESC. As vezes o foco vai para lugares exotéricos e aí o usuário vai pensar que o ESC deixou de funcionar. Fora que, você vai ter que lembrar de por o listener lá, caso adicione um novo componente.

Tentei colocá-lo na mesma classe onde instacio os forms, onde ficam os listeners e o método dos Action mas ele apresenta vários erros:
ActionMap cannot be resolved to a type, JComponent cannot be resolved entre outros.

O que estou fazendo de errado?

Aquele código para para ir no construtor do seu JFrame.

O meu construtor do FormPrincipal é assim:

public class FormPrincipal extends JDialog {
	public FormPrincipal(Frame owner) {
		super(owner);
		
		initComponents();
	}

	public FormPrincipal(Dialog owner) {
		super(owner);
		initComponents();
	}

Colocando aquele código no construtor ele fca pedindo para fazer Casting, diz que tem método não implementado etc etc…
Obs.: Utilizo JFormDesigner para fazer os forms…

Ah, desculpe, é que o getContentPane() retorna um objeto do tipo container. Erro meu.
Troque o getCotentPane() pelo painel principal da sua classe e deve funcionar. Ou faça um cast para JPanel antes.

        JPanel painel = (JPanel)getContentPane();
        InputMap imap = painel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);   
        imap.put(KeyStroke.getKeyStroke("ESCAPE"), "SairDoPrograma");   
          
        //Mapeamos o botão ESC a ação descrita pela string.   
        ActionMap amap = painel.getActionMap();   
          
        //Mapeia a string para a ação a ser executada.   
        amap.put("SairDoPrograma", new AbstractAction() {   
            @Override   
            public void actionPerformed(ActionEvent e) {   
                  System.exit(0);   
            }   
        });       

Deu certo Vinicius, entretanto, não fica estranho eu dar ações dentro da classe Form não? Sempre tive na mente que a interface com o usuário é feita na classe principal! (me corrija se estiver errado!). Agora consigo eliminar o excesso de listeners! Mas aquele velho problema no scrollpane ainda não está resolvido, ou está e não to vendo? hehehehee
Obrigado!!!

[quote=JoAuM]Deu certo Vinicius, entretanto, não fica estranho eu dar ações dentro da classe Form não? Sempre tive na mente que a interface com o usuário é feita na classe principal! (me corrija se estiver errado!). Agora consigo eliminar o excesso de listeners! Mas aquele velho problema no scrollpane ainda não está resolvido, ou está e não to vendo? hehehehee
Obrigado!!![/quote]

Você está completamente errado. De onde você tirou essa idéia?

Professores :lol: .
É costume falarem que o contato com o usuário é feito na classe principal! Ou será que entendi errado?
Não sei se me expliquei mal mas é que, as ações de sair devem passar por uma entrada feita no programa principal, por exemplo, System.exit(0) não cabe à classe do Form fazer e sim ao MAIN. Foi assim que me foi ensinado, mas se não for o correto, mudo agora! :smiley: :smiley: :smiley:

[quote=JoAuM]Professores :lol: .
É costume falarem que o contato com o usuário é feito na classe principal! Ou será que entendi errado?
Não sei se me expliquei mal mas é que, as ações de sair devem passar por uma entrada feita no programa principal, por exemplo, System.exit(0) não cabe à classe do Form fazer e sim ao MAIN. Foi assim que me foi ensinado, mas se não for o correto, mudo agora! :smiley: :smiley: :smiley:
[/quote]

Programa e classe são coisas completamente diferentes, logo “programa principal” e “classe que tem o método main” também são coisas completamente diferentes. Para o usuário, se o programa apresenta a tela com 1 ou 1.000.000 de classes, não faz a menor diferença.

O que você tem que prezar é aqueles velhos conceitos de OO que continuam completamente válidos até hoje, mas que a maior parte do pessoal não entende corretamente: Encapsulamento; Alta coesão e Baixo acoplamento. Estes três conceitos são razoavelmente bons para medir a qualidade do seu sistema. Não tendo isso o sistema sai tosco e cheio de problemas. Tendo isso, o resto (polimorfismo, MVC, padrões de projeto, etc) é conseqüência desses três.