Action Buttons css style in JavaFX ControlFX dialog

10,204

Solution 1

Note

In a more recent question, this time regarding the new Dialog API bundled with JDK8u40 early releases, I came with a less hacky and more clean solution, using stylesheets instead of inline styles and lookups.

So I'm updating this question, as openjfx-dialogs is still the way to have dialogs for the official releases 8u20, 8u25 and 8u31.

New solution

To customize the default style of a dialog with our own css file, we need to take into consideration that the dialog is in fact a new stage, with a new scene, and the root node is a DialogPane instance.

So once we have some dialog instance:

@Override
public void start(Stage primaryStage) {        
    Alert alert = new Alert(AlertType.CONFIRMATION);
    alert.setTitle("Confirmation Dialog");
    alert.setHeaderText("This is a Custom Confirmation Dialog");
    alert.setContentText("We override the style classes of the dialog");
    ...
}

we can access to its dialog pane and add our own style sheet:

DialogPane dialogPane = alert.getDialogPane();
dialogPane.getStylesheets().add(
   getClass().getResource("myDialogs.css").toExternalForm());

In order to define our rules we need to know the descriptors already used. For that, we just need to look for dialog.css file in the openjfx-dialogs.jar (under the package com.sun.javafx.scene.control.skin.modena), or go to the source code at the repository.

Now we need to provide our custom rules to override the default ones for dialog and alert class selectors. The following rules will have the exact same effect as the inline styiling from my first answer.

.dialog > .dialog-pane {
    -fx-background-color: greenyellow;
}

.dialog > .dialog-pane > .button-bar {
    -fx-font-size: 24px;
    -fx-background-color: indianred;
    -fx-font-family: "Andalus";
}

.dialog > .dialog-pane > .content.label {
    -fx-font-size: 16px;
    -fx-font-weight: bold; 
    -fx-fill: blue;
}

.dialog:header > .dialog-pane .header-panel {
    -fx-background-color: cadetblue;
    -fx-font-style: italic;
}

.alert.confirmation.dialog-pane {
    -fx-graphic: url("lock24.png");
}

Solution 2

Since you don't provide the version you are using, I'll go with the new OpenJFX-Dialogs project (source, started since 8.20.7 version), which are by the way the same dialogs we'll have with JDK8u40.

Firts, let's add some alert dialog:

@Override
public void start(Stage primaryStage) {
    Alert alert = new Alert(AlertType.CONFIRMATION);
    alert.setTitle("Confirmation Dialog");
    alert.setHeaderText("This is a Regular Confirmation Dialog");
    alert.setContentText("This is the message");

    Button button = new Button("Click to display an alert");
    button.setOnAction(e->{
        Optional<ButtonType> result = alert.showAndWait();
        result.ifPresent(System.out::println);
    });

    Scene scene = new Scene(new StackPane(button), 300, 200);
    primaryStage.setScene(scene);
    primaryStage.show();
}

Regular Alert Dialog

Now, to style this dialog, we need an instance of DialogPane, which is the root node within a dialog, where the header, the content and the buttons are displayed.

Via lookups or via getChildren() it's easy to find these components.

This is an example of customizing all of the components of the dialog:

@Override
public void start(Stage primaryStage) {
    Alert alert = new Alert(AlertType.CONFIRMATION);
    alert.setTitle("Confirmation Dialog");
    alert.setHeaderText("This is a Custom Confirmation Dialog");
    alert.setContentText("We override the style classes of dialog.css");

    Button button = new Button("Click to display an alert");
    button.setOnAction(e->{
        Optional<ButtonType> result = alert.showAndWait();
        result.ifPresent(System.out::println);
    });

    Scene scene = new Scene(new StackPane(button), 300, 200);
    primaryStage.setScene(scene);
    primaryStage.show();

    DialogPane dialogPane = alert.getDialogPane();
// root
    dialogPane.setStyle("-fx-background-color: greenyellow;");

// 1. Grid
    // remove style to customize header
    dialogPane.getStyleClass().remove("alert");

    GridPane grid = (GridPane)dialogPane.lookup(".header-panel"); 
    grid.setStyle("-fx-background-color: cadetblue; "
            + "-fx-font-style: italic;");

    // custom icon
    StackPane stackPane = new StackPane(new ImageView(
            new Image(getClass().getResourceAsStream("lock24.png"))));
    stackPane.setPrefSize(24, 24);
    stackPane.setAlignment(Pos.CENTER);
    dialogPane.setGraphic(stackPane);

// 2. ContentText with just a Label
    dialogPane.lookup(".content.label").setStyle("-fx-font-size: 16px; "
            + "-fx-font-weight: bold; -fx-fill: blue;");

// 3- ButtonBar
    ButtonBar buttonBar = (ButtonBar)alert.getDialogPane().lookup(".button-bar");
    buttonBar.setStyle("-fx-font-size: 24px;"
            + "-fx-background-color: indianred;");
    buttonBar.getButtons().forEach(b->b.setStyle("-fx-font-family: \"Andalus\";"));

}

And this is how it looks like:

Custom Alert Dialog

Solution 3

Another solution:

dialog.getDialogPane().getScene().getStylesheets().add("css_name.css");

https://bitbucket.org/controlsfx/openjfx-dialogs/src/7273358fd294d486b4959f0c89b24b76c49bec89/src/main/resources/com/sun/javafx/scene/control/skin/modena/dialog.css?at=default

Share:
10,204

Related videos on Youtube

John Gamarra González
Author by

John Gamarra González

Im blind, not deaf

Updated on July 04, 2022

Comments

  • John Gamarra González
    John Gamarra González almost 2 years

    I've been using ControlsFX dialogs to show information, but the style of my application is not blue, and does not match dialog style (color, borders) is there a way to change the button color or styles?

  • jewelsea
    jewelsea over 9 years
    While it may be a basically a link only answer it does include a significant line of code and I actually prefer this answer to the accepted one. I wish I could retract my downvote.
  • José Pereda
    José Pereda over 9 years
    @jewelsea This was also the solution I gave on a recent question related to dialogs in JDK8u40. Do you want me to edit this answer and add this?
  • jewelsea
    jewelsea over 9 years
    I'd prefer a new answer to this question José which demonstrates styling of ControlsFX dialogs using stylesheets in the same way that your answer to the recent question demonstrated styling built-in JavaFX dialogs. I think sample solutions that demonstrate how to style dialogs are better if they use stylesheets rather than inline setStyle calls and lookups.