0

I have an alert. I'm adding two ButtonTypes to it. I'm also adding a stylesheet to it. But how can I make the Discard changes red? I have already a btn-red class in my CSS file.

Alert alert = new Alert(AlertType.CONFIRMATION);
//setting up content text
alert.getDialogPane().getStylesheets().add("file:src/start/styles.css");

ButtonType discardChanges = new ButtonType("Discard Changes");
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(discardChanges, buttonTypeCancel);
.btn-red {
    -fx-background-color: #c41010;
    -fx-text-fill: #ffffff;
}

It would be nice if the Discard changes has a red button of danger.

Thank you in advance! :)

SDG6
  • 91
  • 1
  • 8

2 Answers2

1

After playing around with this problem for some time the best solution I could come up with was going through all children of the DialogPane and finding the correct button.

alert.getDialogPane().getChildren().forEach(node -> {
    if (node instanceof ButtonBar) {
        ButtonBar buttonBar = (ButtonBar) node;
        buttonBar.getButtons().forEach(possibleButtons -> {
            if (possibleButtons instanceof Button) {
                Button b = (Button) possibleButtons;
                if (b.getText().equals("Discard Changes")) {
                    b.setStyle("-fx-background-color: #c41010;  -fx-text-fill: #ffffff;");
                }
            }
        });
    }
});

There may be better solutions but this one should work just fine.

b.jm021
  • 11
  • 3
  • @SDG6 Note if you don't want to use inline CSS (i.e. you want to continue to use an external stylesheet) then you can do the same as above but give the button(s) an ID that you can reference in CSS (e.g. `b.setId("discardBtn")` → `#discardBtn { /* CSS */ }`). – Slaw Mar 07 '21 at 22:26
  • @Slaw Ow okay. That's even a better solution. Thank you! – SDG6 Mar 08 '21 at 19:21
  • @SDG6 And actually, I didn't look at the code above closely enough. The more appropriate way to get the buttons is to call [`DIalogPane#lookupButton(ButtonType)`](https://openjfx.io/javadoc/15/javafx.controls/javafx/scene/control/DialogPane.html#lookupButton(javafx.scene.control.ButtonType)). It returns a `Node` since the button can be any `Node`, but by default it will be a `Button`. If you want to loop over all buttons then do `for (var type : dialogPane.getButtonTypes()) { var btn = dialogPane.lookupButton(type); /* do something */ }`. – Slaw Mar 08 '21 at 20:47
1

You can give each button a CSS ID (or style class) so that you can reference it in your stylesheet. You should make use of DialogPane#lookupButton(ButtonType) to get a reference to the button. That method returns a Node since the button can be implemented with any type of Node; however, by default the returned object will be an instance of Button.

For example:

Alert alert = new Alert(AlertType.CONFIRMATION);
//setting up content text
alert.getDialogPane().getStylesheets().add("<path-to-css-resource>");

ButtonType discardChanges = new ButtonType("Discard Changes");
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(discardChanges, buttonTypeCancel);

// Add CSS ID
Node discardButton = alert.getDialogPane().lookupButton(discardChanges);
discardButton.setId("discardBtn");
// Or style class
// discardButton.getStyleClass().add("red-btn");

Then in the CSS:

/* Or use the .red-btn style class */
#discardBtn {
  -fx-background-color: #c41010;
  -fx-text-fill: #ffffff;
}

Two notes:

  1. You may want to replace the above CSS with something like:

    #discardBtn {
      -fx-base: #c41010;
    }
    

    The -fx-base is a "looked-up color" which is how modena.css implements a theme. By setting that value your button will still have all the hover/armed effects applied by modena.css, just red instead of the default grayish color. The text will also be white due to how modena.css sets the text color.

    You can take a look at modena.css to see what looked-up colors it defines and how it uses them.

  2. The path you're using to add the stylesheet is suspect. If the stylesheet is a resource then the path should look something more like:

    alert.getDialogPane().getStylesheets().add(getClass().getResource("/styles.css").toString());
    

    Assuming src is the root of your source files/resource files (i.e. "root" of the class-path).

Slaw
  • 37,820
  • 8
  • 53
  • 80