我发现当我在Java swing应用程序中显示一个JDialog
或新的JFrame
时,我的中文输入法在Windows7中会从半字节模式切换到全字节模式。
为什么调用对话框或frame setVisible(true)
方法会切换我的输入法设置?
有没有人知道代码出了什么问题,或者是Java的bug?
重现问题的步骤:
运行application.
中的按钮
我的语言设置
我发现了一个类似的问题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();
}
}
});
}
}
发布于 2014-07-07 18:46:09
根据Oracle documentation的说法,从我对这个问题的理解来看,这似乎是我所期望的:
应用程序的默认区域设置通过三种方式确定。首先,除非您显式更改了缺省值,否则Locale.getDefault()方法将返回最初由Java Virtual Machine (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允许客户端组件获取当前输入法或键盘布局的区域设置。
发布于 2014-07-08 21:41:46
我认为这可能与Windows 7记住每个运行的应用程序的键盘/语言设置有关:
的其余部分保留ES
这也适用于JVM应用程序,例如Eclipse,所以我认为这不是JVM语言环境问题。
发布于 2014-07-13 04:04:20
首先,OP的代码中有一个bug。让我输入正确的内容:
l = new Locale("zh", "TW");
OP的意思是半宽/全宽(不是半字节/全字节)。在全角模式下,英文字母将使用多个字节,例如A而不是A。这可以使用Shift-Space进行切换。
IME简介
在区域和语言中,您可以选择一种语言,以及多个键盘。以简体中文为例,至少有三种常用键盘:
这够复杂了吗?我还有更多要告诉你的:在微软拼音之类的键盘下,有一些模式,允许你在键入中文的同时,为逗号、句号和其他标点符号选择Unicode符号或ASCII符号。是的,我可以先输入中文单词。,、一段时间,然后我就可以切换模式,然后我就可以用.,\
什么?我正在用中文输入法输入英文吗?是的,除了美国的中文输入法键盘外,微软的拼音键盘也有只输入英文的模式。因此,如果我想输入英语,我可以使用美国英语
,或中文美国键盘
,或具有英文模式的中文Microsoft拼音键盘
。
我的答案
OP明确想要的是切换键盘,甚至切换键盘下的模式,而不是切换语言。在Java中,可以通过很多方式设置语言环境,但不能设置键盘,也不能设置模式。如果我希望我的Java Swing应用程序切换到使用中文ShuangPin键盘的模式,对于中文输入,但使用英文标点符号,该怎么办?
纠正我,如果我错了,但有没有的方式为Java选择一个特定的输入法,或模式的本机键盘。这是一篇关于在Windows甚至Mac上开发IME的文章。我希望这能解释很多。
http://blog.gatunka.com/2009/09/20/ime-basics-for-developers/
但是,如果操作员只想让用户在密码字段中输入英语,那么他有很多解决方案。但这不是他所说的。
https://stackoverflow.com/questions/24489808
复制相似问题