【发布时间】:2014-12-09 15:53:56
【问题描述】:
向我的应用添加 DatePicker 时,我得到以下信息:
我认为这是因为我在计算机上使用希伯来语。 如何将 DatePicker 的语言更改为英语?
【问题讨论】:
标签: javafx datepicker javafx-8
向我的应用添加 DatePicker 时,我得到以下信息:
我认为这是因为我在计算机上使用希伯来语。 如何将 DatePicker 的语言更改为英语?
【问题讨论】:
标签: javafx datepicker javafx-8
您可以为调用 Java 虚拟机的实例定义默认语言环境:
Locale.setDefault(Locale.ENGLISH);
或者,如果您找不到语言环境,您需要在预先制作的常量中,在officially supported locales 列表中查找国家代码并创建您的“自定义”语言环境,如下所示:
Locale.setDefault(Locale("cs")) //locale for Czech language
关于start 方法。如果您还想为文本编辑器实现自定义格式化程序,您也应该将语言环境添加到格式化程序。
这只是一个例子:
private final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("EEEE, d.MM.uuuu", Locale.ENGLISH);
@Override
public void start(Stage primaryStage) {
Locale.setDefault(Locale.ENGLISH);
DatePicker datePicker=new DatePicker();
datePicker.setValue(LocalDate.now());
datePicker.setConverter(new StringConverter<LocalDate>() {
@Override
public String toString(LocalDate object) {
return object.format(formatter);
}
@Override
public LocalDate fromString(String string) {
return LocalDate.parse(string, formatter);
}
});
StackPane root = new StackPane(datePicker);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
编辑
根据设计,DatePicker 使用Locale.getDefault() 以应用于弹出窗口上显示的控件的所有格式。这可以在com.sun.javafx.scene.control.skin.DatePickerContent 类中检查。
除非您为更改这些格式化程序的控件提供自定义外观,否则为了将DatePicker 内容更改为英文,避免进一步更改其他本地化控件,解决方法可能是:
private final Locale myLocale = Locale.getDefault(Locale.Category.FORMAT);
@Override
public void start(Stage primaryStage) {
DatePicker datePicker=new DatePicker();
datePicker.setValue(LocalDate.now());
datePicker.setOnShowing(e-> Locale.setDefault(Locale.Category.FORMAT,Locale.ENGLISH));
datePicker.setOnShown(e-> Locale.setDefault(Locale.Category.FORMAT,myLocale));
...
}
编辑 2
回到setOnShown 上的原始区域设置为时过早,因为如果用户更改月份,则会使用原始区域设置并且不会正确显示。要工作,它应该在setOnHiding 和setOnAction 上都关闭。
private final Locale myLocale = Locale.getDefault(Locale.Category.FORMAT);
@Override
public void start(Stage primaryStage) {
DatePicker datePicker=new DatePicker();
datePicker.setValue(LocalDate.now());
datePicker.setOnShowing(e-> Locale.setDefault(Locale.Category.FORMAT,Locale.ENGLISH));
datePicker.setOnHiding(e-> Locale.setDefault(Locale.Category.FORMAT,myLocale));
datePicker.setOnAction(e-> Locale.setDefault(Locale.Category.FORMAT,myLocale));
...
}
【讨论】:
从 fx9 开始,皮肤被移到公共 api 中 - 所以你可能考虑创建一个自定义皮肤,允许配置每个选择器的区域设置。不幸的是,进行内部格式化的类仍然隐藏在内部,所以调整需要变脏。
如果你敢于/被允许访问内部,一种方法是
getLocale() 以首先检查选择器的属性是否包含自定义区域设置 - 如果是则返回,否则委托给 super
示例代码:
public class DatePickerLocale extends Application {
/**
* Custom DatePickerContent that uses a per-picker Locale if
* available.
*/
public static class XDatePickerContent extends DatePickerContent {
public XDatePickerContent(DatePicker datePicker) {
super(datePicker);
}
@Override
protected Locale getLocale() {
if (datePicker != null) {
Object locale = datePicker.getProperties().get("CONTROL_LOCALE");
if (locale instanceof Locale) {
return (Locale) locale;
}
}
return super.getLocale();
}
}
/**
* Custom DatePickerSkin that injects a custom content.
*/
public static class XDatePickerSkin extends DatePickerSkin {
public XDatePickerSkin(DatePicker control) {
super(control);
}
@Override
public Node getPopupContent() {
DatePickerContent content = (XDatePickerContent) getDatePickerContent();
if (!(content instanceof XDatePickerContent)) {
content = new XDatePickerContent((DatePicker) getSkinnable());
replaceDatePickerContent(content);
}
return content;
}
//------------- going dirty: reflective access to super
protected DatePickerContent getDatePickerContent() {
return (DatePickerContent) FXUtils.invokeGetFieldValue(DatePickerSkin.class, this, "datePickerContent");
}
protected void replaceDatePickerContent(DatePickerContent content) {
FXUtils.invokeSetFieldValue(DatePickerSkin.class, this, "datePickerContent", content);
}
}
private Parent createContent() {
LocalDate now = LocalDate.now();
DatePicker picker = new DatePicker(now) {
@Override
protected Skin<?> createDefaultSkin() {
return new XDatePickerSkin(this);
}
};
Locale customLocale = Locale.CHINA;
// config locale for content
picker.getProperties().put("CONTROL_LOCALE", customLocale);
// config locale for chronology/converter
picker.setChronology(Chronology.ofLocale(customLocale));
picker.setConverter(new LocalDateStringConverter(FormatStyle.SHORT,
customLocale, picker.getChronology()));
// just to see some formats with default locale
List<String> patterns = List.of("e", "ee", "eee", "eeee", "eeeee");
HBox box = new HBox(10);
patterns.forEach(p -> {
DateTimeFormatter ccc = DateTimeFormatter.ofPattern(p);
String name = ccc.withLocale(Locale.getDefault(Locale.Category.FORMAT)).format(now);
box.getChildren().add(new Label(name));
});
BorderPane content = new BorderPane(picker);
content.setBottom(box);
return content;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent(), 400, 200));
stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(DatePickerLocale.class.getName());
}
【讨论】: