Search code examples
javaswingunicodejtextfield

German characters in JTextField


I'm working on a Java application for people learning German, and I have run into a problem with the special characters of this language. I want to make a subclass of JTextField that will interpret ALT + a as ä, ALT + o as ö and so on, while behaving as usual for all ASCII characters.

My attempts so far:

public class GermanTextField extends JTextField implements KeyListener{
  public GermanTextField() {
    init();
  }
   
  // other constructors ...
  
  private void init() {
    addKeyListener(this);
  }

  
  
  public void keyPressed(KeyEvent arg0) {}


  public void keyReleased(KeyEvent arg0) {}


  public void keyTyped(KeyEvent evt) {
    if(evt.getKeyChar() == 'o' && evt.isAltGraphDown()){
      setText(getText() + "ö");
      evt.consume();
    }
  }


}

Code above does not work (GermanTextField behaves like standard JTextField), and when I print evt.getKeyChar() to console this is what I get:

?
?
?
?

This may be due to my own language, because ALT + o produces ó on my system. Of course I could have done it like that:

  public void keyTyped(KeyEvent evt) {
    if(evt.getKeyChar() == 'ó'){
      setText(getText() + "ö");
      evt.consume();
    }
  }

But it probably won't work on any systems other than Polish.

My question is: is there any solution to this problem that will behave as expected on systems with different language settings?


Full solution to this problem, based on MvGs answer:

package daswort.gui;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JTextField;

public class GermanTextField extends JTextField implements KeyListener{
  
  private Map<Integer, String> transform = 
      new HashMap<Integer, String>();
  
  public GermanTextField() {
    init();
  }


  public GermanTextField(int columns) {
    super(columns);
    init();
  }


  public GermanTextField(String text, int columns) {
    super(text, columns);
    init();
  }


  public GermanTextField(String text) {
    super(text);
    init();
  }

  
  private void init() {
    transform.put(KeyEvent.VK_A, "äÄ");
    transform.put(KeyEvent.VK_U, "üÜ");
    transform.put(KeyEvent.VK_O, "öÖ");
    
    addKeyListener(this);
  }

  
  
  public void keyPressed(KeyEvent evt) {
    if(evt.isAltGraphDown()){
      String umlaut = transform.get(evt.getKeyCode());
      if(umlaut != null){
        int idx = evt.isShiftDown() ? 1 : 0;
        setText(getText() + umlaut.charAt(idx));
      }
    }
  }

  public void keyReleased(KeyEvent arg0) {}


  public void keyTyped(KeyEvent evt) {
    if(evt.isAltGraphDown()){
      evt.consume();
    }
  }


}

Solution

  • To identify key events independent of the current locale, don't use getKeyChar. Instead, use isKeyCode() to identify the key independent of the character associated with it. Like this:

    if (evt.getKeyCode() == KeyEvent.VK_O && evt.isAltGraphDown())
    

    This should match Alt Gr + O on any keyboard layout.