我在询问之前在网上搜索并搜索了我的问题的答案,但是找不到这样的内容。
我希望我的应用程序用户能够根据他们的选择从JavaFX ColorPicker和整个应用程序窗口颜色,按钮颜色,字体等更新中选择一种颜色。我的应用程序中有很多屏幕,我不想在每个窗格上设置setStyle()以确保颜色发生变化我希望有一些类型的CSS文件,其中的颜色可以根据ColorPicker中选择的颜色。这可能吗?我的意思是我意识到你可以通过Java代码编写一个文本文件并给它一个" .css"扩展,但有没有其他方法来实现这一目标?
"最佳做法是什么"对于FX中的这类事情?
答案 0 :(得分:3)
有一些颜色,影像中的一切都基于这些颜色。我在某个地方有一个例子,我现在找不到,但基本上是
-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());
等,当用户选择新颜色时,一切都会更新。