为什么设置JDialog或JFrame setVisible(true)来切换我的IME设置?

时间:2014-06-30 12:07:39

标签: java swing jdialog ime

我发现当我在Java swing应用程序中显示JDialog或新JFrame时,我将在Windows 7中将中文输入法从半字节模式切换到全字节模式。

为什么调用对话框或框架setVisible(true)方法来切换我的IME设置?

有谁知道代码有什么问题,或者它是Java的错误?

重现问题的程序:

  1. 运行该应用程序。
  2. 将您的语言更改为中文输入法之一,例如。中文(繁体) - 快速
  3. 点击程序中的按钮
  4. 我的语言设置

    enter image description here

    我找到了类似的问题Automatic toggling of character width by Windows 7 input methods in Java

    并且在添加默认语言环境后,它仍无效

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

4 个答案:

答案 0 :(得分:5)

根据Oracle documentation,似乎我的行为与我所期望的一样,从我如何理解这个问题:

  

应用程序的默认语言环境以三种方式确定。首先,除非您明确更改了默认值,否则Locale.getDefault()方法将返回Java虚拟机(JVM)在首次加载时最初确定的区域设置。也就是说,JVM从主机环境确定默认语言环境。主机环境的区域设置由主机操作系统和在该系统上建立的用户首选项确定。

在您的问题中,应用程序启动后,Windows 中的默认值已更改,这意味着已设置JVM语言环境。设置了特定框架的区域设置,但是新框架的创建基于默认区域设置(对于JDialog和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);
 }

由于您在Windows中设置默认语言环境,因此可以认为JComponent.getDefaultLocale()将返回Windows语言环境。 getDefaultLocale()本身返回当前应用程序上下文(VM语言环境)的语言环境。调用以下方法将设置当前上下文的语言环境:

javax.swing.JComponent.setDefaultLocale(locale);

设置VM的默认语言环境(实际上调用

SwingUtilities.appContextPut(defaultLocale, l);

使得发生的事情稍微明显一点。)

如果设置defaultLocale修复了问题,我想在调用链的其他地方调用defaultLocale会导致Windows更改设置。


如果这不能为您提供预期的功能,我认为建议您调查的唯一其他属性是InputContext类:

  

提供控制文本输入工具的方法,例如输入法和键盘布局。两种方法处理输入方法和键盘布局:selectInputMethod允许客户端组件按区域设置选择输入方法或键盘布局,getLocale允许客户端组件获取当前输入方法或键盘布局的区域设置。

答案 1 :(得分:4)

我认为这可能与Windows 7记住每个正在运行的应用程序的键盘/语言集有关:

  1. 我打开浏览器(在本例中为Chrome)。我可以在任务栏中看到我的键盘组是ES(西班牙语)。
  2. 然后我打开任何其他应用程序。什么都没有改变。
  3. 我再次在浏览器中设置焦点。
  4. 我按Alt + Shift,这是更改键盘设置的快捷方式。现在我可以看到EN(英文)
  5. 我点击其他应用程序的窗口(或者我使用Alt + TAB)。我的键盘设置更改为ES
  6. 每次我回到浏览器时,键盘设置都会更改为EN,保留ES用于其他应用程序。
  7. 这也适用于JVM应用程序,例如Eclipse,因此我认为它不是JVM Locale问题。

答案 2 :(得分:3)

首先,OP的代码中存在一个错误。让我输入正确的内容:

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

OP意味着半宽/全宽(不是半字节/全字节)。在全宽模式下,英文字母将使用多个字节,例如A而不是A.这可以使用Shift-Space切换。

IME简介

在区域和语言中,您可以选择一种语言,以及许多键盘。例如,简体中文语言,至少有三种常用键盘:

  1. 美国键盘允许用户输入英文,无法输入中文

  2. Microsoft拼音键盘允许用户输入拼写并选择正确的字符

  3. ShuangPin允许用户使用较少的击键输入拼写

  4. 仅为简体中文添加了Window 7中的更多键盘。

  5. 那复杂吗?我还有更多要告诉你:在微软拼音之类的键盘之下,有一些模式,允许你在输入中文时为逗号,句号和其他标点选择Unicode符号或ASCII符号。是的,我可以先用。一段时间键入中文单词,然后我可以切换模式,然后我可以输入中文。,\

    什么?我正在用中文IME输入英文?是的,除了中文IME中的美国键盘外,微软拼音键盘还具有只键入英语的模式。所以,如果我想输入英语,我可以使用美国英语

    enter image description here,或中文美式键盘

    enter image description here,或带英文模式的中文Microsoft拼音键盘

    enter image description here

    我的回答

    OP明确要求的是在一个键盘下切换键盘,甚至是模式,而不是切换语言。可以在Java中以很多方式设置Locale以更改语言,但不能使用键盘,而不是模式。如果我希望我的Java Swing应用程序切换到带有中文双键键盘的模式,中文输入但是带有英文标点符号怎么办?

    如果我错了,请纠正我,但有 NO 方式让Java为某个IME或模式选择本机键盘。这是一篇关于Windows甚至Mac中的IME开发的文章。我希望能够解释很多

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

    但是如果OP只是想让用户输入密码字段的英文,那么他有很多解决方案。但这不是他所说的。

答案 3 :(得分:1)

我做了一个简单的测试:

我打开IE,选择了一个标签,在地址栏中,将中文IME设置为半宽。然后单击另一个选项卡,IME会自动更改为全宽。

所以我认为它与Java没有任何关系。这是Windows / IME的行为。