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?!
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.
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.
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.
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.