Вот несколько конкретных примеров динамической установки цветов темы для заданных компонентов с использованием:
- предложения Фабиана о поиске цветов.
- программно созданные таблицы стилей css, записанные во временные файлы.
Образец с использованием искомых цветов
Что образец делает, устанавливает некоторыестандартного поиска цветов, которые были найдены в modena.css
для стилизации трех вещей, которые вы хотите стилизовать:
- Цвет фона (
-fx-background-color
).Это стандартный фон, используемый в классах, производных от класса Pane
. - Цвет текста (
-fx-text-background-color
).Да, смущенно названный, я знаю, но это, кажется, то, что это, по любой причине. - Цвет для кнопок (
-fx-base
).
В примере приложения пользователь может выбирать цвета динамически, используя элементы управления JavaFX ColorPicker
, чтобы изменять цвета элементов, отображаемых впанель предварительного просмотра.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ThemeMaker extends Application {
@Override
public void start(Stage stage) throws Exception {
Pane previewPane = createPreviewPane();
Pane controlPane = createControlPane(previewPane);
Pane layout = new VBox(
20,
controlPane,
previewPane
);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
private Pane createControlPane(Pane previewPane) {
ColorPicker backgroundColorPicker = new ColorPicker(Color.web("#b3ccff"));
ColorPicker textColorPicker = new ColorPicker(Color.web("#4d804d"));
ColorPicker controlColorPicker = new ColorPicker(Color.web("#ffe6cc"));
GridPane controlPane = new GridPane();
controlPane.setHgap(5);
controlPane.setVgap(5);
controlPane.addRow(0, new Label("Background color:"), backgroundColorPicker);
controlPane.addRow(1, new Label("Text color:"), textColorPicker);
controlPane.addRow(2, new Label("Control color:"), controlColorPicker);
backgroundColorPicker.valueProperty().addListener((observable, oldColor, newColor) ->
setThemeColors(previewPane, backgroundColorPicker.getValue(), textColorPicker.getValue(), controlColorPicker.getValue())
);
textColorPicker.valueProperty().addListener((observable, oldColor, newColor) ->
setThemeColors(previewPane, backgroundColorPicker.getValue(), textColorPicker.getValue(), controlColorPicker.getValue())
);
controlColorPicker.valueProperty().addListener((observable, oldColor, newColor) ->
setThemeColors(previewPane, backgroundColorPicker.getValue(), textColorPicker.getValue(), controlColorPicker.getValue())
);
setThemeColors(previewPane, backgroundColorPicker.getValue(), textColorPicker.getValue(), controlColorPicker.getValue());
return controlPane;
}
private void setThemeColors(Pane previewPane, Color backgroundColor, Color textColor, Color controlColor) {
previewPane.setStyle(
"-fx-background-color: " + toHexString(backgroundColor) + ";" +
"-fx-text-background-color: " + toHexString(textColor) + ";" +
"-fx-base: " + toHexString(controlColor) + ";"
);
}
private Pane createPreviewPane() {
Label label = new Label(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, " +
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
label.setWrapText(true);
Button btn = new Button("Sample Button");
Pane previewPane = new VBox(10, label, btn);
previewPane.setPadding(new Insets(5));
previewPane.setPrefWidth(200);
return previewPane;
}
// from https://stackoverflow.com/a/56733608/1155209 "How to get hex web String from JavaFX ColorPicker color?"
private String toHexString(Color value) {
return "#" + (format(value.getRed()) + format(value.getGreen()) + format(value.getBlue()) + format(value.getOpacity()))
.toUpperCase();
}
private String format(double val) {
String in = Integer.toHexString((int) Math.round(val * 255));
return in.length() == 1 ? "0" + in : in;
}
public static void main(String[] args) {
launch(args);
}
}
Образец с использованием динамических таблиц стилей
Таким образом, цветовое решение поиска очень мощное, потому что вы можете динамически стилизовать цвет всех элементов в сцене.Тем не менее, CSS в целом гораздо мощнее, чем просто настройка цвета.Если для вашей динамической стилизации требуется нечто большее, чем просто настройка цвета, или вам нужны очень конкретные правила для стилизации определенного элемента в сцене, тогда вам понадобится ваша собственная таблица стилей.
Свойство stylesheets
узлов и сцен представляет собой динамический наблюдаемый список.Так что, если вы измените таблицы стилей, вы измените стиль узла или сцены.На каждую таблицу стилей ссылается URL.Таким образом, чтобы динамически создать таблицу стилей, все, что вам нужно сделать, это создать содержимое таблицы стилей в коде и записать его во временный файл, получить ссылку URL на временный файл, а затем установить его в качестве таблицы стилей для того, что вы хотитеto style.
Чтобы привести пример этого подхода, просто возьмите код из предыдущего примера, используя искомые цвета, и замените метод setThemeColors на метод ниже.После этого будет выполнено динамическое оформление панели предварительного просмотра с использованием динамически создаваемого файла CSS, а не искомых цветов.
Примечание. При создании динамической таблицы стилей я пытался использовать селектор .root
для определения стилей(аналогично ответу Саи), но по какой-то причине он не работал (возможно, он не работает с моей версией JavaFX (v13)).Поэтому вместо этого я использовал определенные селекторы CSS для стилей элементов (например, label{-fx-text-fill:<custom-color>}
).Это работало нормально, и, в качестве бонуса, оно демонстрирует дополнительный уровень контроля, который вы можете получить, определяя свои собственные таблицы стилей.
private void setThemeColors(Pane previewPane, Color backgroundColor, Color textColor, Color controlColor) {
try {
Path cssPath = Files.createTempFile("fx-theme-", ".css");
Files.writeString(
cssPath,
".themed{-fx-background-color:"+ toHexString(backgroundColor) +";}" +
".label{-fx-text-fill:"+ toHexString(textColor) +";}" +
".button{-fx-base:" + toHexString(controlColor) + ";}"
);
cssPath.toFile().deleteOnExit();
System.out.println("Wrote " + cssPath);
System.out.println("URL " + cssPath.toUri().toURL().toExternalForm());
previewPane.getStyleClass().setAll("themed");
previewPane.getStylesheets().setAll(
cssPath.toUri().toURL().toExternalForm()
);
} catch (IOException e) {
e.printStackTrace();
}
}
Фон для искомых цветов
Следующая документация скопирована из связанного справочного раздела по JavaFX CSS для искомых цветов ,Это мощный метод для достижения желаемого, и концепция (насколько я знаю) свойственна обработке CSS JavaFX и не существует со стандартным CSS на основе HTML.
С поисковыми цветамивы можете ссылаться на любое другое свойство цвета, установленное на текущем узле или на любом из его родительских элементов.Это очень мощная функция, так как она позволяет определять общую палитру цветов на сцене, а затем использовать ее во всем приложении.Если вы хотите изменить один из этих цветов палитры, вы можете сделать это на любом уровне дерева сцены, и это повлияет на этот узел и все его потомки.Поисковые цвета не ищутся, пока они не применены, поэтому они активны и реагируют на любые изменения стиля, которые могут произойти, такие как замена цвета палитры во время выполнения на свойство "style" на узле.
Если вы будете искать внутри jar-файлов, которые поставляются с JavaFX SDK, который вы используете, вы найдете файл с именем modena.css
.Этот файл предопределяет многие искомые цвета, которые вы можете переопределить, чтобы упростить тему вашего приложения.Они нигде не документированы, вам нужно взглянуть на файл modena.css, чтобы увидеть, какие они есть (самые полезные находятся в разделе .root
файла).Самый важный цвет - -fx-base
, который задает основной цвет для всей системы управления JavaFX.
Просматриваемые цвета часто сочетаются с некоторыми другими концепциями JavaFX CSS, такими как деривация и рендеринг, для создания согласованных тем, которые по-прежнему читаются при изменении базового цвета поиска.Это позволяет изменить базовый цвет, например, с белого на черный, и текст, отображаемый в элементах управления на основе базового цвета, автоматически изменится с обратно на белый, чтобы его можно было читать.
Что такое-fx-base
?
fx-base
- это основной цвет для всех элементов управления, поэтому его установка изменит цвет всех элементов управления в сцене, что, вероятно, вам и нужно, но, возможно, нет.
Если вы хотите изменить только кнопки, а не все в сцене, просто установите цвет -fx-base непосредственно на каждую из кнопок, а не на включающую панель.Один из хитростейших способов сделать это состоит в том, что вы можете определить свой собственный стиль CSS для кнопки и установить для него значение -fx-base: my-custom-color
, а затем динамически установить значение my-custom-color
в вашей программе, как показано в ответе Фабиана.
Обратите внимание, что установка основного цвета предпочтительнее, чем попытка установить фактический цвет кнопки.Потому что, сама кнопка, когда вы смотрите на нее внимательно, включает в себя различные градиенты, и затенение происходит от основного цвета, так что на самом деле она состоит из нескольких цветов при ее рендеринге, а не только из одного цвета.