在提问之前,我在网上搜索并搜索了我的问题的答案,但找不到类似的内容。
我希望我的应用程序用户能够从 JavaFX ColorPicker 中选择颜色,并根据他们的选择更新整个应用程序窗口颜色、按钮颜色、字体等。我的应用程序中有很多屏幕,我真的不想在每个窗格上 setStyle() 以确保颜色发生变化我想要某种类型的 CSS 文件,其中的颜色可以根据所选颜色进行更改在颜色选择器中。这可能吗?我的意思是我意识到你可以通过 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();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以创建一个Theme可供应用程序使用的单个实例,并将所有根节点绑定styleProperty到cssProperty. 或者,您可以添加一个工厂方法Theme来生成根节点:
public <T extends Parent> T createThemedNode(Supplier<T> factory) {
T node = factory.get();
node.styleProperty().bind(cssProperty());
return node ;
}
Run Code Online (Sandbox Code Playgroud)
例如,您可以将其用作
BorderPane root = theme.createThemedNode(BorderPane::new);
Run Code Online (Sandbox Code Playgroud)
如果您使用 FXML,您可以创建类似类型的工厂方法来加载 FXML 文档并绑定结果节点的样式。
最后,当然,你会做类似的事情
ColorPicker baseColorPicker = new ColorPicker();
baseColorPicker.valueProperty().bindBidirectional(theme.baseProperty());
Run Code Online (Sandbox Code Playgroud)
等等,当用户选择新颜色时,所有内容都会更新。