【问题标题】:Changing the language in JavaFX 8 DatePicker更改 JavaFX 8 DatePicker 中的语言
【发布时间】:2014-12-09 15:53:56
【问题描述】:

向我的应用添加 DatePicker 时,我得到以下信息:

我认为这是因为我在计算机上使用希伯来语。 如何将 DatePicker 的语言更改为英语?

【问题讨论】:

    标签: javafx datepicker javafx-8


    【解决方案1】:

    您可以为调用 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 上的原始区域设置为时过早,因为如果用户更改月份,则会使用原始区域设置并且不会正确显示。要工作,它应该在setOnHidingsetOnAction 上都关闭。

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

    【讨论】:

    • 感谢您的回复。但是,更改默认区域设置也会更改其他内容,例如对于美国和欧洲用户(MM/DD、DD/MM)应该不同的日期格式。是否可以在不更改应用程序其余部分的默认语言环境的情况下执行此操作?
    • 感谢您的回复。这行得通,除了在“setOnShown”上返回原始本地为时过早,因为如果用户更改月份,则使用原始语言环境并且它不会正确显示。要工作,应该在“setOnHiding”和“setOnAction”上都关闭它。我将编辑您的回复以反映这一点。
    【解决方案2】:

    从 fx9 开始,皮肤被移到公共 api 中 - 所以你可能考虑创建一个自定义皮肤,允许配置每个选择器的区域设置。不幸的是,进行内部格式化的类仍然隐藏在内部,所以调整需要变脏。

    如果你敢于/被允许访问内部,一种方法是

    • 将应在选择器属性映射中使用的特定于选择器的区域设置
    • 扩展 DatePickerContent(内部类 - 脏!)以覆盖其(公共!这里没有危险)getLocale() 以首先检查选择器的属性是否包含自定义区域设置 - 如果是则返回,否则委托给 super
    • 扩展 DatePickerSkin 以注入(需要反射访问 - 脏!)自定义内容
    • 扩展 DatePicker 以将自定义皮肤作为默认皮肤返回
    • 配置选择器的年表和转换器以使用特定的语言环境 - 这是在编辑器中适当地格式化文本所需要的

    示例代码:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-09
      • 2013-01-15
      相关资源
      最近更新 更多