Exploring Platform Preferences in JavaFX
JavaFX 22 introduces several new features and enhancements. One of the notable additions is the Platform preferences API, which provides developers with a convenient way to access platform-specific preferences and adapt their applications accordingly. In this blog post, we’ll explore the new APIs and demonstrate how to leverage them in your JavaFX applications.
Platform Preferences API
The Platform Preferences API in JavaFX 22 exposes platform-specific preferences as a read-only ObservableMap of key-value pairs. These preferences encompass a wide range of UI settings, including color schemes, background and foreground colors, and accent colors. The API is designed to be platform-independent, providing a consistent interface for accessing preferences across different operating systems.
ColorScheme
One of the key components of the Platform Preferences API is the ColorScheme enumeration, which defines two color schemes for the user interface: LIGHT and DARK. These schemes specify whether applications should prefer light text on dark backgrounds or dark text on light backgrounds, respectively. By incorporating the ColorScheme enumeration into their applications, developers can create themes that seamlessly adapt to the user’s preferred color scheme.
Platform.Preferences
The Platform.Preferences
interface extends the ObservableMap
interface to expose platform preferences as key-value pairs.
The interface defines properties for commonly used preferences such as color scheme, background color, foreground color, and accent color.
Platform#getPreferences
The getPreferences()
method is a static method provided by the Platform
class.
It returns an instance of the Preferences
class, which allows developers to access platform preferences.
ColorScheme Usage
In this blog we will only look at the ColorScheme
usage.
Let’s consider a scenario where you want to adjust the theme of your JavaFX application based on the color scheme.
Preferences preferences = Platform.getPreferences();
ColorScheme colorScheme = preferences.getColorScheme();
if (colorScheme == ColorScheme.DARK) {
// apply dark theme
} else {
// apply light theme
}
We also would like to listen to any changes so this could move into a listener:
Preferences preferences = Platform.getPreferences();
preferences.colorSchemeProperty().addListener((observable, oldValue, newValue) -> {
if (newValue == ColorScheme.DARK) {
// apply dark theme
} else {
// apply light theme
}
});
Example
To demonstrate the usage, let’s write a JavaFX application and update its styling based on the ColorScheme
:
import javafx.application.Application;
import javafx.application.ColorScheme;
import javafx.application.Platform;
import javafx.application.Platform.Preferences;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class PlatformPreferencesDemo extends Application {
@Override
public void start(Stage primaryStage) {
Label label = new Label("Hello, JavaFX!");
StackPane root = new StackPane();
root.getChildren().add(label);
Scene scene = new Scene(root, 300, 200);
// Apply platform color scheme preferences
Preferences preferences = Platform.getPreferences();
if (preferences != null) {
ColorScheme colorScheme = preferences.getColorScheme();
updateTheme(colorScheme, scene);
}
// Add a listener to update on color scheme changes
preferences.colorSchemeProperty().addListener((observable, oldValue, newValue) -> updateTheme(newValue, scene));
primaryStage.setScene(scene);
primaryStage.setTitle("Platform Preferences Demo");
primaryStage.show();
}
private void updateTheme(ColorScheme colorScheme, Scene scene) {
if (colorScheme == ColorScheme.DARK) {
// Remove light stylesheet, add dark stylesheet
scene.getStylesheets().remove(getClass().getResource("light-theme.css").toExternalForm());
scene.getStylesheets().add(getClass().getResource("dark-theme.css").toExternalForm());
} else {
// Remove dark stylesheet, add light stylesheet
scene.getStylesheets().remove(getClass().getResource("dark-theme.css").toExternalForm());
scene.getStylesheets().add(getClass().getResource("light-theme.css").toExternalForm());
}
}
public static void main(String[] args) {
launch(args);
}
}
/* Define styles for the dark color scheme */
/* Set background color */
.root {
-fx-background-color: #333333;
}
/* Set text color */
.label {
-fx-text-fill: white;
}
/* Define styles for the light color scheme */
/* Set background color */
.root {
-fx-background-color: #f0f0f0;
}
/* Set text color */
.label {
-fx-text-fill: black;
}
Here is a video of how the application reacts the appearance changes on a mac:
Conclusion
The introduction of the Platform Preferences API opens up new possibilities for creating platform-aware applications that seamlessly integrate with the user’s preferred settings. By leveraging this API, developers can enhance the user experience and ensure consistency across different operating systems. Whether it’s adapting color schemes, customizing UI elements, or fine-tuning application behavior, the Platform Preferences API provides a powerful toolkit for building modern JavaFX applications.
References: