如何将 ControlsFX 字体选择器中的字体应用于标签?

How to apply font from ControlsFX Font Selector to a label?

我正在使用 JavaFX 和 Scene Builder 制作应用程序

我有标签:

@FXML
private Label category1;

当我点击切换按钮时,它会调用方法:

@FXML
void changeFont(ActionEvent event) {
try {
  FontSelectorDialog fs = new FontSelectorDialog(null);
  fs.setTitle("Select Font");
  fs.setHeaderText("");
  fs.setContentText("asdasdada");
  fs.show();

} catch (Exception e) {
  System.out.println("can't load new window");
}

}

它显示了 ControlFX FontSelector 对话框,我可以在其中选择字体系列、字体样式和字体大小, 还有两个按钮 "OK" 和 "CANCEL"

单击 "OK" 按钮时如何将此对话框中的更改应用到我的标签?

编辑:

我已经在 "en" 和 "US" 的代码中尝试了该行,但没有任何反应。

FontSelectorDialog fs = new FontSelectorDialog(null);
      fs.setTitle("Select Font");
      fs.setHeaderText("");
      Localization.setLocale(new Locale("en", "US"));
      fs.show();
      fs.setOnCloseRequest(e -> {
        if (fs.getResult() != null) {
          category1.setFont(fs.getResult());
        }
      });

    } catch (Exception e) {
      System.out.println("can't load new window");
    }

但语言没有改变。我还找到了带有语言的文件,我想在那里用俄语编辑文件

其他语言有这样的字符串:

但是俄语有奇怪的符号:

我不知道如何更改这些符号以使示例文本变成英文。 有什么想法吗?

编辑 2: 我试过你的版本,但没有任何反应。我什至尝试在 Main class 中使用 Localization,没有结果

Locale locale = Localization.getLocale();
      Localization.setLocale(new Locale("en", "US")); // en-US
      FontSelectorDialog fs = new FontSelectorDialog(null);
      fs.show();
      fs.setOnCloseRequest(e->{
        if (fs.getResult() != null) {
          category1.setStyle(null);
          category1.setFont(fs.getResult());
        }
        Localization.setLocale(locale); // Reset locale
      });

我复制了文件 controlsfx.properties,将名称更改为 controlsfx_en_US.properties

但是当我将此文件粘贴到包含其他文件的目录时出现警告对话框,即使没有该名称的文件:

我也试过把名字改成 controlsfx_eng_USA.properties,但出现警告对话框:"File couldn't be created"

show 不等待用户响应,您必须轮询 result 属性 以获得结果,例如关闭字体对话框时:

fs.setOnCloseRequest(e -> {
    if (fs.getResult() != null) {
        category1.setFont(fs.getResult());
    }
});

如果您想等待用户响应(我假设这就是您想要的),您可以使用 showAndWait。为此,只需替换

fs.show();

Optional<Font> optional = fs.showAndWait();
if (optional.isPresent()) {
    category1.setFont(optional.get());
}

有关详细信息,请参阅 showAndWait and show

编辑 1: 关于答案 "EDIT: @Topaco I've tried your code"

css 似乎有问题,更准确地说是 -fx-font-size: 2em; 行。问题与字体对话框(或 show- / showAndWait-方法)本身没有直接关系,也是一个简单的问题 由于某些原因,category1.setFont(...) 不能与 css 结合使用。

解决方案取决于您的代码。如果您在 fxml 中设置了标签的 styleClass-属性,一个可能的解决方案是定义字体大小 outside css 使用 style-属性:

<Label fx:id="category1" ... styleClass="category-label" style="-fx-font-size: 2em;"/>

.category-label {
    -fx-background-color: #8CA5FF;
    -fx-text-fill: #fff;
    -fx-padding: 0 0 0 20px;
}

然后,在设置字体之前使用 category1.setStyle(null):

删除样式
fs.setOnCloseRequest(e->{
    if (fs.getResult() != null) {
        category1.setStyle(null);
        category1.setFont(fs.getResult());
    }
});

这应该有效。

编辑 2: 关于答案 "EDIT: Thanx @Topaco for the Answer, it works! But I would like also to modify another thing"

ControlsFX 元素中显示的语言由 Localization.getLocale() 返回的语言环境控制。如果没有使用 Localization.setLocale(...) 明确设置语言环境,则使用 Locale.getDefault() 返回的默认语言环境(例如,参见 ControlsFX Dialogs and Localization. Generally, the latter is determined by the JVM from the host-system (e.g. see how do I set the default locale for my JVM?)。

因此,我假设您的默认语言环境是自动采用的俄罗斯语言环境,因为您可能没有使用 Localization.setLocale(...) 设置语言环境。

一个可能的解决方案是在 start 方法的最开始设置语言环境

Localization.setLocale(new Locale("en","US")); 

影响所有 ControlsFX 元素的语言为美国英语。

如果只更改字体对话框的语言,请在 changeFont 方法的最开始设置语言环境,并在最后将其重置为旧值:

@FXML
void changeFont(ActionEvent event) {
    try {
        Locale locale = Localization.getLocale(); 
        Localization.setLocale(new Locale("en", "US")); 
        FontSelectorDialog fs = new FontSelectorDialog(null);
        fs.show();
        fs.setOnCloseRequest(e->{
            if (fs.getResult() != null) {
                category1.setStyle(null);
                category1.setFont(fs.getResult());
            }
            Localization.setLocale(locale); // Reset locale
        });
    } catch (Exception e) {
        System.out.println("can't load new window");
    }
}

当然,还有更多的可能性,例如您可以更改主机系统中的设置(这当然也会在您的应用程序之外产生巨大影响,并且很可能您真的不希望这样做)或在开始时在应用程序范围内更改默认区域设置start-方法与 Locale.setDefault(...)(影响所有元素,而不仅仅是 ControlsFX 元素)。

编辑 3:关于问题的编辑部分

1)有两个小问题。首先,与前面编辑部分中的声明相反,en-US-locale 必须设置为

Localization.setLocale(new Locale("", ""));

如下所述。其次,您必须在创建 FontSelectorDialog 实例之前 调用该方法,即在 [=41= 的 最开始 ]-方法,例如:

@FXML
void changeFont(ActionEvent event) {
    try {
        Locale locale = Localization.getLocale(); 
        Localization.setLocale(new Locale("", "")); // en-US
        FontSelectorDialog fs = new FontSelectorDialog(null);
        fs.show();
        fs.setOnCloseRequest(e->{
            if (fs.getResult() != null) {
                category1.setStyle(null);
                category1.setFont(fs.getResult());
            }
            Localization.setLocale(locale); // Reset locale
        });
    } catch (Exception e) {
        System.out.println("can't load new window");
    }
}

该代码仅更改字体对话框的语言。作为替代方案,在 start 方法的 最开始 处调用 Localization.setLocale(...) 没有任何问题,该方法改变了整个 ControlsFX 元素的语言申请。

Localization.setLocale(...) 方法也在 ControlsFX Dialogs 部分 "Localizing the Dialogs" 的第 5 点中进行了描述。

这里没有其他事情可以让它工作,特别是没有必要用英文文本替换 controlsfx_ru_RU.properties 文件中的俄文文本.相反,那是完全错误的做法,见下文

2) 关于您的属性文件:这 正是 从中读取语言信息的来源,即如果您使用 Localization.setLocale(...) 将语言环境设置为俄罗斯语言环境,信息从 controlsfx_ru_RU.properties 读取。

在此上下文中,请注意属性文件名称中的两个后缀,例如controlsfx_ru_RU.properties、"ru"、"RU"分别用于实例化Localization.setLocale(...)方法设置的Locale。因此,俄语语言环境设置为

Localization.setLocale(new Locale("ru", "RU"));

en-US 是从 controlsfx.properties 读取的默认语言。因此,en-US-locale 设置为

Localization.setLocale(new Locale("", ""));

不是 Localization.setLocale(new Locale("en", "US")); 乍一看。

一般情况下,您不必更改属性文件 - 唯一的例外是您希望将原始文本替换为自定义文本。为此,您必须按以下步骤进行:复制属性文件,然后在副本中进行更改,最后将副本放入项目的 src 文件夹中。现在,使用副本(带有自定义文本)代替原始属性文件。 这也在 ControlsFX Dialogs 部分 "Localizing the Dialogs" 的第 1 - 4 点中进行了描述。

注意:如您所见,每个属性文件对应于属性文件名称中的后缀定义的特定语言。不打算使用名称中指定的语言以外的语言。我明确提到这一点是因为您在编辑后的问题中指出用 english 文本替换俄语属性文件中的俄语文本。 不要这样做(无论是在原始属性文件中还是在副本中)!这只会让人感到困惑,而且根本没有必要(如上所述)。

3) 关于"strange symbols":这些符号是Unicode-codepoints defining cyrillic letters, e.g. \u041F is the codepoint defining the cyrillic capital letter PE, see Cyrillic script in Unicode。所以如果你例如想要用新的俄语文本替换 controlsfx_ru_RU.properties 文件中的当前俄语文本,您必须使用与新俄语文本的字母相对应的 unicode 代码点。