19

I found that when I show a JDialog or a new JFrame in my Java swing application will toggle my Chinese Input Method from half-byte mode to full-byte mode in Windows 7.

Why does calling the dialog or frame setVisible(true) method toggle my IME setting?

Does anyone knows what's wrong with the code, or it's a bug of Java?

Procedure to reproduce the problem:

  1. run the application.
  2. change your Language to one of Chinese Input methods eg. Chinese (Traditional) - Quick
  3. click the button in the program

My language setting

enter image description here

I have found a similar question Automatic toggling of character width by Windows 7 input methods in Java

and after adding the default locale, it's still not working

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Locale;

public class MainWindow {

private JFrame frame;
private Locale l;

/**
 * Create the application.
 */
public MainWindow() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {

    l = new Locale("zh", "zh_TW");

    frame = new JFrame();
    frame.setLocale(l);
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JButton btnNewButton = new JButton("New button");
    btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {

            JDialog d = new JDialog(frame, "Run", true);
            d.getContentPane().add(new JLabel("dsad"));
            d.setMinimumSize(new Dimension(150, 100));
            d.setLocationRelativeTo(null);
            d.setLocale(l);
            d.setVisible(true);

        }
    });
    frame.getContentPane().add(btnNewButton, BorderLayout.CENTER);
}

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MainWindow window = new MainWindow();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}


}
Community
  • 1
  • 1
user2492632
  • 211
  • 1
  • 5
  • 1
    @Andrew Thompson most of us, we are prisoniers of IDE by default (has a few enhacements :-) incl. this one – mKorbel Jun 30 '14 at 12:34
  • 1
    @mKorbel Oh come on. Doesn't your IDE allow you to define your own templates? If not, get a better one. ;) – Andrew Thompson Jun 30 '14 at 12:39
  • @AndrewThompson I has already reported it to java, but it has been almost 2 weeks and no reply, could you suggest some keywords for me to search the database? – user2492632 Jun 30 '14 at 12:44
  • Search terms I'd start with are "Swing IME" or "Swing Input Method Verification" possibly with "Locale" added or substituted (for either term). – Andrew Thompson Jun 30 '14 at 12:47
  • BTW - I found my way from `Control Panel` | `Clock, Language and Region` | to a `Region and Language` dialog. But it looks different to what is shown above. How to get that dialog on Windows 7? – Andrew Thompson Jul 05 '14 at 02:53
  • I see it now: go to the `Keyboard and Languages` **tab** of the `Region and Language` dialog, then activate the `Change keyboards...` button to get the `Text Services and Input Languages` dialog. – Andrew Thompson Jul 05 '14 at 03:09
  • I would be inclined to see if setting different look and feels effects the same problem. – javajon Jul 05 '14 at 05:38
  • I had a try with setting different look and feel, the problem still exists. Click "Help > About" in the jGoodies demo, will show the problem. http://www.jgoodies.com/download/demos/looks/looksdemo.jnlp – user2492632 Jul 05 '14 at 06:40
  • @AndrewThompson Thanks for trying to draw attention for this question – user2492632 Jul 05 '14 at 06:43
  • If an input field gets the focus after `setVisible(true)` is called, then it's a Windows thing. IME automatically toggles to the default when an input field is focused; unless the specific flag is set in Region and Language settings. That is also pointed out by Splash's answer below. – mostruash Jul 06 '14 at 15:58

4 Answers4

5

According to the Oracle documentation, it seems as though this is behaving as I would expect, from how I understood the question:

The default locale of your application is determined in three ways. First, unless you have explicitly changed the default, the Locale.getDefault() method returns the locale that was initially determined by the Java Virtual Machine (JVM) when it first loaded. That is, the JVM determines the default locale from the host environment. The host environment's locale is determined by the host operating system and the user preferences established on that system.

In your question, the default was changed in Windows after the application was started, which means the JVM locale was already set. The locale for a specific frame was set, but the creation of a new frame sets the locale based on the default locale (which happens for both JDialog and JFrame):

 protected void dialogInit() {
     enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
     setLocale( JComponent.getDefaultLocale() );
     setRootPane(createRootPane());
     setRootPaneCheckingEnabled(true);
     if (JDialog.isDefaultLookAndFeelDecorated()) {
         boolean supportsWindowDecorations =
         UIManager.getLookAndFeel().getSupportsWindowDecorations();
         if (supportsWindowDecorations) {
             setUndecorated(true);
             getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
         }
     }
     sun.awt.SunToolkit.checkAndSetPolicy(this, true);
 }

Since you are setting the default locale in Windows, one would think that JComponent.getDefaultLocale() would return the Windows locale. getDefaultLocale() itself returns the locale of the current application context (the VM locale). Calling the below method will set the locale for the current context:

javax.swing.JComponent.setDefaultLocale(locale);

That sets the default locale for the VM (it actually calls through to

SwingUtilities.appContextPut(defaultLocale, l);

which makes it slightly more apparent what is happening).

If setting the defaultLocale fixes the problem, I imagine that somewhere else in the call chain the defaultLocale is getting called in a manner that causes Windows to change the setting.


If that doesn't give you the expected functionality, the only other property I can think to suggest that you look into is the InputContext class:

Provides methods to control text input facilities such as input methods and keyboard layouts. Two methods handle both input methods and keyboard layouts: selectInputMethod lets a client component select an input method or keyboard layout by locale, getLocale lets a client component obtain the locale of the current input method or keyboard layout.

Jared
  • 753
  • 1
  • 7
  • 14
  • This is not a correct answer as this only changed the language to other than what OP wanted, the zh_TW. The OP wanted to set to half-wdith in language zh_TW which can't be achieved in any of the methods described in this answer. – Splash Jul 15 '14 at 03:11
  • neither javax.swing.JComponent.setDefaultLocale(locale); or InputContext gives the effect i want, InputContext can preserve the keyboard layout, but it didn't solve the auto toggling to full width problem – user2492632 Jul 22 '14 at 13:12
4

I think it can be related to the fact that Windows 7 remembers the keyboard/language set for each running application:

  1. I open my browser (in this case Chrome). I can see in my taskbar my keyboard set is ES (Spanish).
  2. Then I open any other application. Nothing changes.
  3. I set the focus in the browser again.
  4. I press Alt+Shift, which is a shortcut to change the keyboard set. Now I can see is EN (English)
  5. I click on the other app's window (or I use Alt+TAB). My keyboard set changes to ES
  6. Every time I come back to the browser the keyboard set changes to EN, keeping the ES for rest of applications.

This works also for JVM applications, for example Eclipse, so I think it is not a JVM Locale issue.

Pablo Lozano
  • 9,189
  • 2
  • 34
  • 56
  • 1
    I posted this too, but it was deleted by moderator. Some IME has multiple options, some Windows are international version, some are English version with IME. I don't think this behaves has anything to do with Java. – Splash Jul 11 '14 at 03:38
  • i agree it is not a locale problem, i am going to change the project to SWT. the dialog from SWT has no problem at all – user2492632 Jul 22 '14 at 11:36
3

First, there is a bug in the OP's code. Let me just type what is correct:

l = new Locale("zh", "TW");

And what OP meant is Half-Width/Full-Width (not half byte/full byte). In a full-width mode, an English letter will use more than one byte, such as A instead of A. This can be switched using Shift-Space.

Introduction to IME

In Region and Language, you can select a language, plus many keyboards. Simplified Chinese language for example, has least three commonly used keyboard:

  1. US keyboard allows a user to type English, no way to type Chinese

  2. Microsoft Pinyin keyboard allows a user to type the spelling and choose the correct character

  3. ShuangPin allows user to type the spelling with less key strokes

  4. There are more keyboards in Window 7 to be added just for Simplified Chinese.

Is that complicated enough? I have more to tell you: under one of the keyboard such as Microsoft Pinyin, there are modes, to allow you to select a Unicode symbol or a ASCII symbol for comma, period, and other punctuations, while you are typing Chinese. Yes, I can first type Chinese words with 。,、 for a while, then I can switch the mode and from then I can type Chinese with .,\

What? I am typing English in Chinese IME? Yes, besides the US Keyboard in Chinese IME, the Microsoft Pinyin keyboard also has mode to just type English. So if I want to type English, I can use US English language

enter image description here, or Chinese language US Keyboard

enter image description here, or Chinese language Microsoft Pinyin Keyboard with English mode

enter image description here.

My Answer

What OP explicitly wants is to switch the keyboard, or even the mode under one keyboard, instead of switching the language. The Locale can be set in a lot of ways in Java to change the language, but not the Keyboard, no the modes. What if I want my Java Swing application to switch to the mode with Chinese ShuangPin keyboard, for Chinese input but with English punctuation?

Correct me if I am wrong but there is NO way for Java to select a native keyboard for a certain IME, or a mode. Here is an article about IME development in Windows and even Mac. I hope that can explain a lot

http://blog.gatunka.com/2009/09/20/ime-basics-for-developers/

But if the OP just wants to the user to type English for a password field, then he has a lot of solutions. But this is not what he said.

Hai Bi
  • 1,133
  • 1
  • 9
  • 21
1

I did a simple test:

I opened IE, selected a tab, and at the address bar, set Chinese IME to be half width. Then click another tab, the IME change to full width automatically.

So I don't think it had anything to do with Java. It's a Windows/IME behavior.

Splash
  • 1,238
  • 1
  • 15
  • 33
  • i did the same test, but it didn't change to full width mode, instead it changed to "Chinese (Traditional) - Quick" English half width mode from Chinese half width mode. before new tab: http://i.imgur.com/ypzI902.jpg after new tab: http://i.imgur.com/zFCfNuk.jpg – user2492632 Jul 06 '14 at 19:15
  • It has also to do with the Windows Regional setting. What was your default Keyboard for the Default input language? – Splash Jul 06 '14 at 19:20
  • Chinese (Traditional) US Keyboard, you can find it on the first image of the question – user2492632 Jul 06 '14 at 19:24
  • i changed my default keyboard to Chinese - Quick, it also didn't change to full width – user2492632 Jul 06 '14 at 19:30
  • So if your default keyboard is Chinese US Keyboard, then you click a new tab, the IME became the US Keyboard. After you change your default keyboard, could you restart your computer to try again for both IE new tab and the java application. – Splash Jul 06 '14 at 19:35
  • after changing my default keyboard and restarting my pc, IE still didn't change to full width. and the java application changed to full width when it is launched – user2492632 Jul 06 '14 at 19:46