[RESOLVIDO]Capturar evento 'Ç' ou 'ç' foi apertado

Galera tentei sozinho e tentei e tentei mas eu não consigo capturar quando a tecla ‘Ç’ é apertada¬¬ Eu uso InputMap e ActionMap, não trato os eventos com KeyListeners.
Com as outras letras do alfabeto e números não tenho problema( pelo menos não ainda ). Tenho apenas com o CEDILHA.
Meu método processaTeclas() está assim:

    private void processaTeclas() {  
            botoesA = visaoPrincipal.getBotoesA();  
            /** * Captura o InputMap sempre que a janela atual está em foco e captura o ActionMap */  
            InputMap iMap  = visaoPrincipal.getPainelPrincipal().getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW );  
            ActionMap aMap = visaoPrincipal.getPainelPrincipal().getActionMap();  
              
            /** * Associa as ações aos objetos da classe Interna e associa as teclas aos Actions Maps para botões numéricos*/  
            for( int i = 0; i < 10; i++ ) {  
                String actionName = "botaoN" + i;  
                aMap.put( actionName, acaoBotoesNumericos[i] = new BotaoNumericoAcao(i) );  
                iMap.put( KeyStroke.getKeyStroke("" + i), actionName );  
                iMap.put( KeyStroke.getKeyStroke("NUMPAD" + i), actionName );  
            }  
              
            /** * Associa as ações aos objetos da classe Interna e associa as teclas aos Actions Maps para botões de texto( alfabeto ) */  
            for( int i = 0; i < 27; i++ ) {  
                String actionName = "botaoA" + i;  
                String letra      = botoesA[i].getText();  
                aMap.put( actionName, acaoBotoesAlfabeto[i] = new BotaoAlfabetoAcao(i) );  
                iMap.put( KeyStroke.getKeyStroke(letra), actionName );  
            }  
    }  

E minha classe BotaoAlfabetoAcao está assim:

/**
* Classe interna responsável por capturar as teclas de texto( alfabeto ) e passar para a camada Model - Dados
*/
private class BotaoAlfabetoAcao extends AbstractAction {   
      int n;
        
      public BotaoAlfabetoAcao( int n ) {
            this.n = n;
      }

      @Override
      public void actionPerformed( ActionEvent e ) {
            dados.setAreaDeTexto(n);
      }
}

Ai voce me pergunta, ué mas por que voce passa um número para o construtor de BotaoAlfabetoAcao e ele passa um numero para a areaDeTexto? Porque eu estou tentando fazer esse programa em MVC com swing, então botei as coisas separadas, Essa classe é a controller, e na dados, ele sabe o que notificar a visão de acordo com o que ele recebe. No caso como estou recebendo um INTEIRO, ele vai pegar esse inteiro na Model - Dados, que é o inteiro representando o número do elemento do botão no array. La na model, eu tenho um array com os botoes do alfabeto. E no caso se eu passar o valor 1() ele vai chamar o construtor sobrecarregado vai pegar o valor 1 e corresponder ao botao[1] = que é a letra B e vai exibir na tela, entendeu? Funciona com todos, menos com o CEDILHA.

EDIT: Só para constar, além do : “DEAD_CEDILLA”, já tentei “Ç” e ‘Ç’ e também não dá

[quote=wellington.nogueira]Pra mim isto funcionou:

[code] ActionMap actionMap = panel.getActionMap();
InputMap inputMap = panel.getInputMap();

	String meuCedilha = "MEU_CEDILHA";
	actionMap.put(meuCedilha, new AbstractAction() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("<<<<<<<<>>>>>>>>>");
		}
	});
	
	inputMap.put(KeyStroke.getKeyStroke('Ç'), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke('ç'), meuCedilha);

[/code][/quote]

+1

O meu erro deve estar em algum outro lugar então. Talvez no array ou na classe.

Galera no caso você estão usando um método apenas, vou tentar postar aqui desde o começo para vê se vocês conseguem me ajudar que eu não estou conseguindo encontrar o meu erro de lógica de jeito nenhum.

Classe InterfaceGraficaPrincipal:

/** * O texto de cada botão é a letra correspondente. Ex: o texto do botaA é igual a &quot;A&quot;, o texto do botaoCedilha é igual a &quot;Ç&quot;, ou seja, quando eu der um &quot;.getText()&quot; no arrayDeBotao[numero].getText()&quot; ele tem que retornar uma String com o &quot;A&quot; ou &quot;B&quot; ou &quot;Ç&quot;, dependendo do Botão.
private void armazenaBotoesA() {
        botoesA[0] = botaoA;
        botoesA[1] = botaoB;
        botoesA[2] = botaoC;
        botoesA[3] = botaoD;
        botoesA[4] = botaoE;
        botoesA[5] = botaoF;
        botoesA[6] = botaoG;
        botoesA[7] = botaoH;
        botoesA[8] = botaoI;
        botoesA[9] = botaoJ;
        botoesA[10] = botaoK;
        botoesA[11] = botaoL;
        botoesA[12] = botaoM;
        botoesA[13] = botaoN;
        botoesA[14] = botaoO;
        botoesA[15] = botaoP;
        botoesA[16] = botaoQ;
        botoesA[17] = botaoR;
        botoesA[18] = botaoS;
        botoesA[19] = botaoT;
        botoesA[20] = botaoU;
        botoesA[21] = botaoV;
        botoesA[22] = botaoW;
        botoesA[23] = botaoX;
        botoesA[24] = botaoY;
        botoesA[25] = botaoZ;
        botoesA[26] = botaoCedilha;
}

public JButton[] getBotoesA() {
        return botoesA;
}

Classe ControleTecladoAlfanumerico

private void processaTeclas() {
        botoesA = visaoPrincipal.getBotoesA();
        /** * Captura o InputMap sempre que a janela atual está em foco e captura o ActionMap */
        InputMap iMap  = visaoPrincipal.getPainelPrincipal().getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW );
        ActionMap aMap = visaoPrincipal.getPainelPrincipal().getActionMap();
        
        /** * Associa as ações aos objetos da classe Interna e associa as teclas aos Actions Maps para botões numéricos*/
        for( int i = 0; i &lt; 10; i++ ) {
            String actionName = &quot;botaoN&quot; + i;
            aMap.put( actionName, acaoBotoesNumericos[i] = new BotaoNumericoAcao(i) );
            iMap.put( KeyStroke.getKeyStroke(&quot;&quot; + i), actionName );
            iMap.put( KeyStroke.getKeyStroke(&quot;NUMPAD&quot; + i), actionName );
        }
        
        /** * Associa as ações aos objetos da classe Interna e associa as teclas aos Actions Maps para botões de texto( alfabeto ) */
        for( int i = 0; i &lt; 27; i++ ) {
            String actionName = &quot;botaoA&quot; + i;
            String letra      = botoesA[i].getText();
            aMap.put( actionName, acaoBotoesAlfabeto[i] = new BotaoAlfabetoAcao(i) );
            iMap.put( KeyStroke.getKeyStroke(letra), actionName );
        }
}

E classe Interna BotaoAlfabetoAcao:

/**
     * Classe interna responsável por capturar as teclas de texto( alfabeto ) e passar para a camada Model - Dados
     */
    private class BotaoAlfabetoAcao extends AbstractAction {   
        int n;
        
        public BotaoAlfabetoAcao( int n ) {
            this.n = n;
        }

        @Override
        public void actionPerformed( ActionEvent e ) {
            dados.setAreaDeTexto(n);
        }
}

E classe Dados:

/** * Cria um array de Botões para armazenar os botões com as letras do alfabeto  */
private JButton[] botoesA = visaoPrincipal.getBotoesA();

/** * Configura/Notifica a área de texto da Visão para números */
public void setAreaDeTexto( String t ) {
        visaoPrincipal.getAreaDeTexto().setText( visaoPrincipal.getAreaDeTexto().getText() + t );
}
    
/** * Configura/Notifica a área de texto da Visão para texto( alfabeto ) */
public void setAreaDeTexto( int e ) {
        String letra = botoesA[e].getText();
        visaoPrincipal.getAreaDeTexto().setText( visaoPrincipal.getAreaDeTexto().getText() + letra );
}

Oi,

Você já tentou dar um:

System.out.println(arrayDeBotao[numero].getText());

Para ver qual letra é realmente mostrada?

:smiley:

Tchauzin!

[quote=lina]Oi,

Você já tentou dar um:

System.out.println(arrayDeBotao[numero].getText());

Para ver qual letra é realmente mostrada?

:smiley:

Tchauzin![/quote]

Sim, e o Ç é mostrado

Oi,

Que estranho! Estou quebrando a cabeça aqui pra te ajudar…

Coloca um Sysout aqui ó:

@Override public void actionPerformed( ActionEvent e ) { System.out.println("setArea: "+n); dados.setAreaDeTexto(n); }

Tchauzin!

[quote=lina]Oi,

Que estranho! Estou quebrando a cabeça aqui pra te ajudar…

Coloca um Sysout aqui ó:

@Override  
public void actionPerformed( ActionEvent e ) {  
    System.out.println("setArea: "+n);  
    dados.setAreaDeTexto(n);  
}  

Tchauzin![/quote]

Independente de não terem resolvido meu problema, pelo menos estão tentando me ajudar. Obrigado.
Pelo visto acho que isso que você falou, já ajuda um pouco. Eu fiz isso. E fui digitando letra por letra, não na ordem do teclado, mas sim na ordem alfabetica. E saída no console foi essa:

setArea: 0
setArea: 1
setArea: 2
setArea: 3
setArea: 4
setArea: 5
setArea: 6
setArea: 7
setArea: 8
setArea: 9
setArea: 10
setArea: 11
setArea: 12
setArea: 13
setArea: 14
setArea: 15
setArea: 10
setArea: 17
setArea: 18
setArea: 19
setArea: 20
setArea: 21
setArea: 22
setArea: 23
setArea: 24
setArea: 25

Ou seja, todas funcionaram, menos o Ç, eu apertei e nada aconteceu. E o meu Cedilha não está ruim, eu consigo digita-lo em outros programas e ja testei o programa em outro computador também e da no mesmo.

Tenho quase certeza que não é esse problema pois as outras letras também poderiam ser char mas eu usei String no lugar.

Se alguém quiser ver o código do programa inteiro para melhor visualização e me ajudar estarei postando aqui para download. Agradeço a ajuda de vocês e peço que ainda me ajudem, estou quebrando a cabeça para tentar encontrar esse maldito problema. Não quero deixa-lo de lado pois isso é experiência que se adquire.

Será que é isso mesmo wellington.nogueira ?

Bom eu tentei usar o char e não apareceu nenhuma tecla dessa vez:

// NA CLASSE CONTROLE
/** * Associa as ações aos objetos da classe Interna e associa as teclas aos Actions Maps para botões de texto( alfabeto ) */
        for( int i = 0; i &lt; 26; i++ ) {
            String actionName = &quot;botaoA&quot; + i;
            char letra      = botoesA[i].getText().charAt(0);
            aMap.put( actionName, acaoBotoesAlfabeto[i] = new BotaoAlfabetoAcao(i) );
            iMap.put( KeyStroke.getKeyStroke(letra), actionName );
        }
// NA CLASSE DADOS
/** * Configura/Notifica a área de texto da Visão para texto( alfabeto ) */
    public void setAreaDeTexto( int e ) {
        char letra      = botoesA[e].getText().charAt(0);
        visaoPrincipal.getAreaDeTexto().setText( visaoPrincipal.getAreaDeTexto().getText() + letra );
    }

[quote=wellington.nogueira]Debugando o KeyStroke, os caminhos que cada sobrecarga de getKeyStroke toma é muito diferente…

Recomendo trocar de String para char e retestar.

O próprio JavaDoc demonstra que há alguma diferença:
http://docs.oracle.com/javase/6/docs/api/javax/swing/KeyStroke.html#getKeyStroke(java.lang.String)

http://docs.oracle.com/javase/6/docs/api/javax/swing/KeyStroke.html#getKeyStroke(char)[/quote]

No post anterior eu troquei e não funcionou. Ou eu troquei errado? Ve la só.

[quote=wellington.nogueira]Achei!!!

inputMap.put(KeyStroke.getKeyStroke(“typed Ç”), meuCedilha);

Para o caso do Ç, precisa colocar o typed antes (não está escrito em lugar nenhum essa obrigatoriedade)[/quote]

Cacete, nem com o typed estou conseguindo. Por favor se tiver como, baixa o meu projeto e tenta modificar que você vai ver que não está funcionando.

Reparei algo que talvez seja interessante. Veja, coloquei Char ao inves de String como você disse. E coloquei um System.out.println no for e na classe interna. No for ele imprimiu tudo, mas na classe interna não. Será que os elementos não estão sendo passados para o construtor? Veja o código e a saída no console?

/** * Associa as ações aos objetos da classe Interna e associa as teclas aos Actions Maps para botões de texto( alfabeto ) */
        for( int i = 0; i &lt; 27; i++ ) {
            String actionName = &quot;botaoA&quot; + i;
            char letra      = botoesA[i].getText().charAt(0);
            aMap.put( actionName, acaoBotoesAlfabeto[i] = new BotaoAlfabetoAcao(i) );
            iMap.put( KeyStroke.getKeyStroke(letra), actionName );
            System.out.println(botoesA[i].getText() + &quot; = &quot; + letra);
        }

private class BotaoAlfabetoAcao extends AbstractAction {   
        int numero;
        
        public BotaoAlfabetoAcao( int n ) {
            numero = n;
        }

        @Override
        public void actionPerformed( ActionEvent e ) {
            dados.setAreaDeTexto(numero);
            System.out.printf( &quot;\n\nElementos: %d&quot;, numero );
        }
    }

Saída no console:

A = A
B = B
C = C
D = D
E = E
F = F
G = G
H = H
I = I
J = J
K = K
L = L
M = M
N = N
O = O
P = P
Q = Q
R = R
S = S
T = T
U = U
V = V
W = W
X = X
Y = Y
Z = Z
Ç = Ç

Está vendo? Os números( elementos ) não foram impressos.

EDIT: Porém usando STRING os elementos são impressos quando eu aperto alguma tecla =/ Ta dificil de depurar essa bosta

Oi,

Não tem um ‘keycode’ para ‘Ç’ ou para qualquer símbolo que necessita de uma segunda tecla. Esse é o problema.

Logo, não tem como usar o KeyStroke dessa forma. Até porque, no teclado americano não existe a tecla Ç.

=/

Tchauzin!

[quote=lina]Oi,

Não tem um ‘keycode’ para ‘Ç’ ou para qualquer símbolo que necessita de uma segunda tecla. Esse é o problema.

Logo, não tem como usar o KeyStroke dessa forma. Até porque, no teclado americano não existe a tecla Ç.

=/

Tchauzin![/quote]

E como que eu vou tratar isso então?

[quote]
Há alguns pequenos erros nele e alguns ajustes:
Primeiro o for para criar os Action/InputMaps
Vc tem um array de 27 objetos (de zero a 26) mas para antes do último (que é justamente o cedilha).
Troquei por <=
for( int i = 0; i <= 26; i++ )
[b][/quote]

Isso na verdade não era erro. Eu tinha mudado quando eu tava tentando tratar o cedilha separadamente do loop entende?[/b]


Fiz as alterações, sendo que esse lance do UpperCase e Lower eu iria fazer depois que resolvesse esse maldito problema. Agora quanto ao charAt não tinha feito. Alias até fiz no outro post e te mostrei mas tava errado em algo.

Tem certeza que alterou a classe Dados? Esse método está o mesmo que o original, sem alteração nenhuma.

[size=18]De qualquer forma…OBRIGADOOOOOOOOOOOOOOOO>>>>> AGORA ESTÁ FUNCIONANDO :smiley: :smiley: :smiley: :smiley: :smiley: :smiley: :smiley: :lol: :lol: :lol: [/size]

Qual era o erro? Tinha algo a ver com o InputMap? E quanto ao maisculo e minusculo, ele não está diferenciado. Quando eu digito, ele exibi sempre em maisculo seja com caps lock ligado ou não. Acredito que tem algo a ver com o metodo na classe Dados. Vou verificar aqui. E quanto ao projeto ser em "MVC", acho que estou conseguindo implementar bem esse padrão em Swing? Tentei fazer de acordo com a documentação que li no site da Oracle. MVC Modificado que tem lá também. Obrigado a todos que me ajudaram. Que disposeram de seu tempo me ajudando. Três dias parado olhando para esse código tentando achar o erro.

[quote=wellington.nogueira]com relação ao método setAreaDeTexto
Tinha um if e == 26 que colocava o Ç. Provavelmente você já tinha alterado o código :wink:

O problema é que o Ç não é algo padrão (como a Lina tinha comentado).

Quando vc usa String no getKeyStroke, ele já entende a letra maiúscula e minúscula porém ele espera caracteres mapeados (VK_algumacoisa), quando usa char, precisa mapear ambos os casos…

Não diria, neste caso que era erro, mas “particularidades” não bem documentadas :wink:
[/quote]

Hmm…Entendi. Caraca essa foi difícil. Só mas uma coisa, você percebeu, quando abriu o programa ai, que no visual editor o layout dele aparece de um jeito e, quando executa, fica de outro jeito? Eu usei layout em tudo, não sei por que ficou assim. Você tem alguma ideia?

[quote=wellington.nogueira][quote=lucas_guj]Hmm…Entendi. Caraca essa foi difícil. Só mas uma coisa, você percebeu, quando abriu o programa ai, que no visual editor o layout dele aparece de um jeito e, quando executa, fica de outro jeito? Eu usei layout em tudo, não sei por que ficou assim. Você tem alguma ideia?[/quote]Desculpe cara, mas não usei Visual Editor não (eu dificilmente uso um editor de telas). Mas o correto mesmo é utilizar layout managers sim.
Só uma observação: O Visual Editor foi “descontinuado” e agora há outro plugin: Window Builder. Há algumas versões do Visual Editor muito “bugadas” :wink: .[/quote]

Cara eu falei visual editor mas falei errado, na verdade quis dizer matisse do netBeans, mas não tem problema não, já consegui resolver, você faz as telas na mão ou usa arrasta e solta?

Pra mim isto funcionou:

[code] ActionMap actionMap = panel.getActionMap();
InputMap inputMap = panel.getInputMap();

	String meuCedilha = "MEU_CEDILHA";
	actionMap.put(meuCedilha, new AbstractAction() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("<<<<<<<<>>>>>>>>>");
		}
	});
	
	inputMap.put(KeyStroke.getKeyStroke('Ç'), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke('ç'), meuCedilha);

[/code]

Não sei se faz muita diferença (e não deveria) mas eu usei o cedilha como char e não como String. Não cheguei a fazer o teste com o cedilha em forma de String.

Fiz uns testes e, pelo menos aqui, o resultado foi no mínimo curioso:

Este primeiro código funciona:

[code]public class TesteField {

public static void main(String[] args) {
	JFrame frame = new JFrame("Frame");
	
	JPanel panel = (JPanel) frame.getContentPane();
	
	ActionMap actionMap = panel.getActionMap();
	InputMap inputMap = panel.getInputMap();
	
	String meuCedilha = "MEU_CEDILHA";
	actionMap.put(meuCedilha, new AbstractAction() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("<<<<<<<<>>>>>>>>>");
		}
	});
	
	inputMap.put(KeyStroke.getKeyStroke('A'), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke('a'), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke('Ç'), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke('ç'), meuCedilha);
	
	frame.setPreferredSize(new Dimension(200, 80));
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.pack();
	frame.setVisible(true);
}

}[/code]

Já este abaixo não funcionou tão bem assim…[code]public class TesteField {

public static void main(String[] args) {
	JFrame frame = new JFrame("Frame");
	
	JPanel panel = (JPanel) frame.getContentPane();
	
	
	ActionMap actionMap = panel.getActionMap();
	InputMap inputMap = panel.getInputMap();
	
	String meuCedilha = "MEU_CEDILHA";
	actionMap.put(meuCedilha, new AbstractAction() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("<<<<<<<<>>>>>>>>>");
		}
	});
	
	inputMap.put(KeyStroke.getKeyStroke("A"), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke("a"), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke("Ç"), meuCedilha);
	inputMap.put(KeyStroke.getKeyStroke("ç"), meuCedilha);
	
	frame.setPreferredSize(new Dimension(200, 80));
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.pack();
	frame.setVisible(true);
}

}[/code]

A única diferença entre o primeiro código e o segundo é que utilizei no primeiro char e no segundo String.