JavaFX CSS Dynamic Styling



在询问之前,我在网上搜索并搜索了问题的答案,但找不到这样的东西。

我希望我的应用程序用户能够从 JavaFX ColorPicker 中选取一种颜色,并根据他们的选择更新整个应用程序窗口的颜色、按钮颜色、字体等。我的应用程序中有很多屏幕,我真的不想在每个窗格上设置Style()以确保颜色发生变化,我希望有某种类型的CSS文件,其中的颜色可以根据在ColorPicker中选择的颜色而变化。这可能吗?我的意思是,我意识到您可以通过Java代码编写文本文件并为其提供".css"扩展名,但是还有其他方法可以做到这一点吗?

外汇中这种事情的"最佳实践"是什么?

摩德纳的所有东西都基于几种颜色。我在某处有一个例子,我现在找不到,但基本上

  • -fx-base
  • -fx-accent
  • -fx-default-button
  • -fx-focus-color
  • -fx-faint-focus-color(与-fx-focus-color相同,但不透明度为 0x22)

因此,在根节点上设置这些内容基本上将主题为整个根及其后代。

最后,当用户在每个根节点上更改它们时,您将不得不以某种方式更新它们,并且您需要提供接线来执行此操作。使用 CSS 文件可能不是一种方法,因为很难确保根据需要重新加载更新的文件。我可能会将事情连接起来,以便在用户更改这些颜色时更改根节点的styleProperty()以定义这些颜色。

您可以考虑创建一个封装这些内容的Theme类:

public class Theme {
private final ObjectProperty<Color> base = new SimpleObjectProperty<>(Color.web("#ececec"));
private final ObjectProperty<Color> accent = new SimpleObjectProperty<>(Color.web("#0096c9"));
private final ObjectProperty<Color> defaultButton = new SimpleObjectProperty<>(Color.web("#abd8ed"));
private final ObjectProperty<Color> focusColor = new SimpleObjectProperty<>(Color.web("#039ed3"));
private final ObjectProperty<Color> faintFocusColor = new SimpleObjectProperty<>(Color.web("039ed322"));
public ObjectProperty<Color> baseProperty() {
return base ;
}
public final Color getBase() {
return baseProperty().get();
}
public final void setBase(Color base) {
baseProperty().set(base);
}
// etc etc
private final ReadOnlyStringWrapper css = new ReadOnlyStringWrapper() ;
public Theme() {
css.bind(Bindings.createStringBinding(() -> String.format(
"-fx-base: %s; "
+"-fx-accent: %s; "
+"-fx-default-button: %s; "
+"-fx-focus-color: %s ; "
+"-fx-faint-focus-color: %s ;",
toRgba(getBase()),
toRgba(getAccent()),
toRgba(getDefaultButton()),
toRgba(getFocusColor()),
toRgba(getFaintFocusColor())),
base, accent, defaultButton, focusColor, faintFocusColor));
}
private String toRgba(Color color) {
int r = (int) (255 * color.getRed());
int g = (int) (255 * color.getGreen());
int b = (int) (255 * color.getBlue());
int a = (int) (255 * color.getOpacity());
return String.format("#%02x%02x%02x%02x", r, g, b, a);
}
public ReadOnlyStringProperty cssProperty() {
return css.getReadOnlyProperty();
}
}

然后,您可以创建可供应用使用的单个Theme实例,并将根节点的所有styleProperty绑定到cssProperty。或者,您可以将工厂方法添加到Theme以生成根节点:

public <T extends Parent> T createThemedNode(Supplier<T> factory) {
T node = factory.get();
node.styleProperty().bind(cssProperty());
return node ;
}

例如,您将其用作

BorderPane root = theme.createThemedNode(BorderPane::new);

如果使用 FXML,则可以创建类似类型的工厂方法来加载 FXML 文档并绑定生成节点的样式。

最后,当然,你会做一些类似的事情

ColorPicker baseColorPicker = new ColorPicker();
baseColorPicker.valueProperty().bindBidirectional(theme.baseProperty());

等等,当用户选择新颜色时,一切都会更新。

最新更新