Identificar se Capslock está ativado ou desativado!

Boa tarde pessoal!

Gostaria de saber como identificar se o CAPSLOCK esta ativo para, caso afirmativo, informar ao usuário no momento de digitar sua senha para autenticação no sistema que está sendo desenvolvido.
Pesquisei sobre o assunto e encontrei diversos tópicos sugerindo o uso do Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK). Porém estou encontrado um problema que também foi descrito por algumas outras pessoas, mas em nenhum lugar encontrei uma solução para o erro ou uma alternativa para fazer essa identificação.

Usando o getLockingKeyState(KeyEvent.VK_CAPS_LOCK) ele me retorna corretamente para o estado inicial do CAPS, ou seja, se o CAPS estiver ativo ele me informa corretamente porém se o estado for alterado em tempo de execução para desativado e eu executar novamente essa consulta ele continua me retornando como se ainda estivesse ativo, e o mesmo acontece para o caso inverso, se eu iniciar com o CAPS desativado.

Alguém teria uma sugestão para implementar essa identificação?!

Use a busca, já tem um tópico igual a esse.

http://www.guj.com.br/java/5682-como-saber-se-capslock-esta-ativado-ou-desativado

[quote=dudis_royer]Use a busca, já tem um tópico igual a esse.

http://www.guj.com.br/java/5682-como-saber-se-capslock-esta-ativado-ou-desativado[/quote]

Como citei no post acima, encontrei diversos tópicos sobre o assunto inclusive esse que me sugeriu, no entanto estou enfrentado um erro implementado da maneira que foi sugerida na maioria dos tópicos. Achei q tivesse sido claro com respeito a isso no meu primeiro post.

Você precisa testar dentro de um KeyListener:

...
campoTexto.addKeyListener(new KeyListener() {
			
	@Override
	public void keyReleased(KeyEvent arg0) {
		boolean capsAtivo = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK);
		JOptionPane.showMessageDialog(null, "Ativo? " + capsAtivo);
	}

	@Override
	public void keyPressed(KeyEvent arg0) { }

	@Override
	public void keyTyped(KeyEvent arg0) { }
});
...

Nesse caso uso o método keyReleased(), ou seja, quando o usuário soltar a tecla digitada, eu sempre verifico se o caps está ligado ou desligado.

Estou usando JavaFX e ideia eh verificar se o CAPS esta ativo tanto no momento que o meu PasswordField receber o focus quanto nos momentos de KeyPressed. Segue abaixo o código do momento do focu:

textSenha.focusedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue) { if (Toolkit.getDefaultToolkit().getLockingKeyState( java.awt.event.KeyEvent.VK_CAPS_LOCK)) { popUpCapsOn.setInfoName("CAPS LOCK ESTÁ ATIVADA"); popUpCapsOn .setInfoDescription("Se a tecla Caps Lock estiver ativada. isso pode fazer\n" + "com que você digite a senha incorretamente.\n\n" + "Você deve pressionar a tecla Caps Lock para desativá-la\n" + "antes de digitar a senha."); Bounds pos = textSenha.localToScene(textSenha.getBoundsInLocal()); popUpCapsOn.show(SascFx.getSascFx().getPainelLogin(), pos.getMaxX(), pos.getMinY() - 20); } } } });

Ai como eu disse, ele funciona pro estado inicial do CAPS, porém quando há alterações no CAPS ele continua mostrando o estado inicial.

Testei o método que te passei e funcionou tranquilo.

Você tentou testar sem focusedProperty() e chamando diretamente pelo addFocusListener(…) no textSenha?

Fiz uns teste simples e constatei que o problema está em utilizar essa detecção é por estar usando com o JavaFx. Fiz dois formulários bem simples contento apenas um TextField e um Label, primeiramente em JavaFx:

[code]public class TestaCapsOnJavaFx extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
	VBox root = new VBox();
	TextField teste = new TextField();
	final Label msg = new Label("CAPS LOCK ESTÁ ATIVADA");
	teste.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
		@Override
		public void handle(KeyEvent arg0) {
			if (Toolkit.getDefaultToolkit().getLockingKeyState(
					java.awt.event.KeyEvent.VK_CAPS_LOCK)) {
				msg.setVisible(true);
			} else {
				msg.setVisible(false);
			}
		}
	});
	msg.setVisible(false);
	root.getChildren().addAll(teste, msg);
	Scene scene = new Scene(root, 200, 100);
	primaryStage.setScene(scene);
	primaryStage.show();
}

/**
 * @param args
 */
public static void main(String[] args) {
	Application.launch(args);
}

}
[/code]

Dessa forma continua apresentando o mesmo erro que citei nos posts acima. Num segundo momento fiz um form usando Swing:

[code]public class TestaCapsOnSwing extends JFrame {

/**
 * 
 */
private static final long serialVersionUID = 1L;

/**
 * @param args
 */
public static void main(String[] args) {
	EventQueue.invokeLater(new Runnable() {
		public void run() {
			try {
				TestaCapsOnSwing frame = new TestaCapsOnSwing();
				frame.setVisible(true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	});
}

public TestaCapsOnSwing() {
	setTitle("Testa Caps Lock");
	setBounds(100, 100, 200, 100);
	setLayout(new BorderLayout());
	JTextField teste = new JTextField();
	final JLabel msg = new JLabel("CAPS LOCK ESTÁ ATIVADA");
	msg.setVisible(false);
	teste.addKeyListener(new KeyListener() {

		@Override
		public void keyTyped(KeyEvent arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void keyReleased(KeyEvent arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void keyPressed(KeyEvent arg0) {
			if (Toolkit.getDefaultToolkit().getLockingKeyState(
					java.awt.event.KeyEvent.VK_CAPS_LOCK)) {
				msg.setVisible(true);
			} else {
				msg.setVisible(false);
			}
		}
	});
	getContentPane().add(teste, BorderLayout.NORTH);
	getContentPane().add(msg, BorderLayout.CENTER);
}

}
[/code]Assim a detecção usando o Toolkit.getDefaultToolkit().getLockingKeyState funcionou como o esperado.

O que infelizmente ainda naum encontrei eh pq isso acontece e como solucionar o problema.

Continuo no aguardo de novas possibilidades de como solucionar o problema envolvendo o Toolkit.getDefaultToolkit().getLockingKeyState juntamente com JavaFx ou novas maneiras de realizar essa detecção.

1 curtida

Bem pessoal, o erro ocorre devido a um bug no método getLockingKeyState() que foi relatado desde 2001 mas infelizmente até o momento sem nenhuma solução (http://bugs.sun.com/view_bug.do?bug_id=4414164). O método em questão só funciona corretamente se o aplicativo criar um Frame e ainda pode incorrer em erro se a alteração do estado no LOCK ocorrer quando o foco estiver em uma janela diferente da que está o Frame.
Como disse o matheusssilva no tópico http://www.guj.com.br/java/210376-monitorando-capslock, é triste ver que uma ferramenta tão poderosa como Java apresente bugs tão antigos que impeçam/dificultem a implementação de coisas relativamente corriqueiras.

1 curtida