javafxjavafx-css

How to separate a border and an effect?


Currently, I have a button with the following CSS:

Button {
    -fx-text-fill: -fx-color-text;
    -fx-font: 15pt "Raleway SemiBold";

    -fx-background-color: -fx-color-theme;
    -fx-background-insets: 0, 0, 0, 0, 0, 1, 2;
    -fx-background-radius: 0;
    -fx-padding: 4px 20px;
    /* -fx-effect: innershadow(two-pass-box, white, 2, 0.2, 0, 0); */
    -fx-border-insets: 0;
    -fx-border-color: black;
}

And it looks like this:

enter image description here

And I'm trying to add an inner shadow to the button. I want the border to show on the outside of this button, which should result in something like this:

enter image description here

I made that in Swing. However, when I try and apply my inner shadow, it draws on top of my border, as shown:

enter image description here

I've tried setting the border insets to -1 (because there isn't an insets property for the effect), but that just moved the effect with it:

enter image description here

My question is: What can I do to ensure that I can see my border around the outside, but keep my effect on the inside?

EDIT: I'm pretty sure that this is a bug in OpenJFX and I've submitted a bug report. Here's some quick code you can use to reproduce the issue:

public class App extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Region example = new Region();
        example.setMaxWidth(100);
        example.setMaxHeight(100);
        example.setEffect(new InnerShadow(BlurType.GAUSSIAN, Color.RED, 10, 0.04, 0, 0));
        example.setStyle("-fx-background-color: white; -fx-border-color: BLUE; -fx-border-width: 5px;");

        StackPane container = new StackPane();
        container.setStyle("-fx-background-color: black;");
        container.setAlignment(Pos.CENTER);
        container.getChildren().add(example);

        Scene scene = new Scene(container, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

EDIT2: This is end up being a bug, and it's been reported here: https://bugs.openjdk.java.net/browse/JDK-8238733


Solution

  • I think the border is getting blended with the effect which is applied. And as you are pretty sure that it could be a bug in JavaFX rendering, below is one way to get it look the way you want.

    You can consider the below solution as when you think like "I definitely want this look only !!" kind of thing :)

    The idea is, instead of setting the effect, you paint the effect manually.

    .button {
        -fx-text-fill: #FFFFFF;
        -fx-font: 15pt "Raleway SemiBold";
        -fx-background-color: #000000, #720D4D, #D03A9A, #DD70B6, #B01378, #CC2C93, #D03A9A, #C81688;
        -fx-background-insets: 0, 1, 1 2 2 1, 1 2 2 2, 2, 2 3 3 2, 2 3 3 3, 3;
        -fx-background-radius: 0;
        -fx-padding: 4px 20px;
        -fx-border-insets: 0px;
        -fx-border-radius: 0px;
        -fx-border-width: 0px;
    }
    

    And the output is as below [ignore the font as I dont have the .tff ;)]:

    enter image description here

    And a closer look for verification purpose:

    enter image description here

    This may not be an actual solution, but can be one alternate (least case).