KCH
KCH

Reputation: 2844

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();
    }
  }


}

Upvotes: 6

Views: 1411

Answers (3)

mKorbel
mKorbel

Reputation: 109813

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

use DocumentFilter for JTextComponents

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?

  • no there aren't,

  • to hope that all PC have got imputed correct value for Locale in Native OS (wrong decision)

  • you are able to wrote any Unicode Chars by using ALT and numbers

  • most safiest is only the setting by useraction about the Locale, then you can to create an array of chars for concrete Locale (own Encode Page)

Upvotes: 1

Ewen
Ewen

Reputation: 1028

The problem is that JTextField uses a different default font than JTextArea. I had the same problem in an application I wrote that had to support multi-languages.

The reason for your problem is that JTextField is normally used to show a mono-spaced font, such as Courier New. Normally Java contains no additional mappings for a mono-spaced graphical font to display Kanji.

The fix you have works, because there is no font named "123", so the default is taken (dialog). The "dialog" font is internally mapped to a font family in the font.properties file of your platform. This will be the same font that JTextField uses.

I have the following fix, to ensure that the same font definition is used in ALL graphical components. You can also find the specific key for JTextField and change it. This way you don't have to worry about the fonts of any component, they will be initialized with dialog. Please enter the following code inside your class containing the JTextField.

Object fontDefinition = new UIDefaults.ProxyLazyValue("javax.swing.plaf.FontUIResource", null, new Obje

java.util.Enumeration keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
    Object key = keys.nextElement();
    Object value = UIManager.get(key);
    if (value instanceof javax.swing.plaf.FontUIResource) {
        UIManager.put(key, fontDefinition);
    }
}

Hope this helps.

Upvotes: 0

MvG
MvG

Reputation: 60868

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.

Upvotes: 6

Related Questions