Подтвердить что ты не робот

Почему настройка JDialog или JFrame setVisible (true) переключает мою настройку IME?

Я обнаружил, что когда я показываю JDialog или новый JFrame, в моем приложении Java swing будет переключать мой китайский метод ввода из полубайтового режима в полнобайтовый режим в Windows 7.

Почему вызов метода диалога или фрейма setVisible(true) переключает мою настройку IME?

Кто-нибудь знает, что не так с кодом, или это ошибка Java?

Процедура воспроизведения проблемы:

  • запустите приложение.
  • измените свой язык на один из китайских методов ввода, например. Китайский (традиционный) - Быстрый
  • нажмите кнопку в программе

Настройки моего языка

enter image description here

Я нашел аналогичный вопрос Автоматическое переключение ширины символов с помощью методов ввода Windows 7 в 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();
            }
        }
    });
}


}
4b9b3361

Ответ 1

Согласно документации Oracle, похоже, что это ведет себя так, как я ожидал, от того, как я понял вопрос:

Стандартная локализация вашего приложения определяется тремя способами. Во-первых, если вы явно не изменили значение по умолчанию, метод 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);

Это устанавливает языковой стандарт по умолчанию для виртуальной машины (на самом деле он вызывает

SwingUtilities.appContextPut(defaultLocale, l);

что делает его несколько более очевидным, что происходит).

Если параметр defaultLocale исправляет проблему, я предполагаю, что где-то еще в цепочке вызовов функция defaultLocale получает вызываемый способ, который заставляет Windows изменять настройку.


Если это не дает вам ожидаемой функциональности, единственное другое свойство, которое я могу предположить предложить, чтобы вы заглянули в InputContext класс:

Предоставляет методы управления средствами ввода текста, такими как методы ввода и раскладки клавиатуры. Два метода обрабатывают как методы ввода, так и раскладки клавиатуры: selectInputMethod позволяет клиентскому компоненту выбирать метод ввода или раскладку клавиатуры по языку, getLocale позволяет клиентскому компоненту получить локаль текущего метода ввода или раскладки клавиатуры.

Ответ 2

Я думаю, это может быть связано с тем, что Windows 7 запоминает набор клавиатуры/языка для каждого запущенного приложения:

  • Я открываю браузер (в данном случае Chrome). Я вижу, что на моей панели задач моя клавиатура - ES (испанский).
  • Затем я открываю любое другое приложение. Ничего не меняется.
  • Я снова установил фокус в браузере.
  • Я нажимаю Alt + Shift, что является ярлыком для изменения набора клавиатуры. Теперь я вижу EN (английский)
  • Я нажимаю на другое окно приложения (или использую Alt + TAB). Моя клавиатура меняется на ES
  • Каждый раз, когда я возвращаюсь в браузер, клавиатура меняется на EN, сохраняя ES для остальных приложений.

Это работает и для приложений JVM, например Eclipse, поэтому я думаю, что это не проблема JVM Locale.

Ответ 3

Во-первых, в коде OP есть ошибка. Позвольте мне просто набрать то, что правильно:

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

И что означает OP, это Half-Width/Full-Width (не байт/полный байт). В режиме полной ширины английская буква будет использовать более одного байта, например A вместо A. Это можно переключить с помощью Shift-Space.

Введение в IME

В области и языке вы можете выбрать язык, а также множество клавиатур. Например, на упрощенном китайском языке используется не менее трех обычно используемых клавиш:

  • Клавиатура US позволяет пользователю вводить английский, не набирать китайский

  • Клавиатура Microsoft Pinyin позволяет пользователю вводить орфографию и выбирать правильный символ

  • ShuangPin позволяет пользователю вводить орфографию с меньшими нажатиями клавиш

  • В Window 7 добавлено больше клавиатур для простоты для упрощенного китайского языка.

Это достаточно сложно? Мне нужно больше рассказать вам: под одной из клавиш, таких как Microsoft Pinyin, есть режимы, позволяющие вам выбирать символ Unicode или символ ASCII для запятой, периодом и другими пунктуациями, пока вы печатаете по-китайски. Да, я могу сначала набрать китайские слова с., какое-то время, тогда я могу переключить режим, и с этого времени я могу набрать китайский язык с., \

Что? Я печатаю английский на китайском IME? Да, помимо американской клавиатуры в китайском IME, клавиатура Microsoft Pinyin также имеет режим просто набирать английский язык. Поэтому, если я хочу набирать текст на английском, я могу использовать американский английский язык

enter image description here, или китайский язык. Клавиатура США

enter image description here или китайский язык Microsoft Pinyin Keyboard с английским режимом

enter image description here.

Мой ответ

Очевидно, что OP явно хочет переключить клавиатуру или даже режим под одной клавиатурой вместо переключения языка. Язык может быть установлен многими способами в Java, чтобы изменить язык, но не клавиатуру, а не режимы. Что делать, если я хочу, чтобы приложение Java Swing переключилось в режим с китайской клавиатурой ShuangPin, для китайского ввода, но с английской пунктуацией?

Исправьте меня, если я ошибаюсь, но есть способ НЕТ для Java, чтобы выбрать собственную клавиатуру для определенного IME или режима. Вот статья о разработке IME в Windows и даже Mac. Я надеюсь, что это может многое объяснить.

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

Но если OP просто хочет, чтобы пользователь набрал английский для поля пароля, у него есть много решений. Но это не то, что он сказал.

Ответ 4

Я сделал простой тест:

Я открыл IE, выбрал вкладку и в адресной строке установил, чтобы китайский IME был половинной шириной. Затем нажмите другую вкладку, IME изменится на полную ширину.

Поэтому я не думаю, что это имело какое-либо отношение к Java. Это поведение Windows/IME.