0

I am using scene builder to design my program. I wanted to add background image so I used a css file to add it. Everything is working perfectly fine but when I try to add a radius to the css file, it does not change a thing. So I tried adding a border and a border radius and it worked perfectly. I do not have any idea why -fx-background-radius:10; is not working.

this is my css code:

.signUp{
    -fx-background-image: url('bg.jpg');
    -fx-background-size: cover;
    -fx-background-radius:10;
    -fx-border-width:5;
    -fx-border-color: "white";
    -fx-border-radius: 10;
}

I also tried to add a background radius on scene builder but it does not change when I already added a style sheet. But when I remove the style sheet and add a background radius, it works. Do anybody knows why this is happening?

Alex
  • 706
  • 7
  • 16
akolangto
  • 33
  • 1
  • 6
  • 2
    As far as i know `-fx-background-radius` works only for color background and not for images – Alex May 26 '21 at 05:56
  • Indeed, the [documentation](https://openjfx.io/javadoc/15/javafx.graphics/javafx/scene/doc-files/cssref.html#region) says *"Each comma-separated value or set of values in the series applies to the corresponding background color."* – James_D May 26 '21 at 11:46

1 Answers1

3

Ok, based on the comments from @Alex & @James_D, now it is quite clear that you cannot control radius for a background-image. But if you are very keen to get the desired behavior(get curved edges to background image) you can set shape to the node to mimic like a background-radius is applied on the background image.

You can build the dynamic shape path based on your required radius and apply the style on the node.

Please check the below demo code. If you have fixed size node, you can directly call updateShape method, if the node size changes, you can call this on width/height listener. Also check the image for a quick preview of how the shape path is built.

[Update :] As per the comments from @Slaw, included a much simpler alternate approach of setting Rectangle as shape and updating its dimensions.

enter image description here

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class BackgroundImageRadiusDemo extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        double radius = 20;
        StackPane signUp = new StackPane();
        signUp.getStyleClass().add("signUp"); // In the .css file it sets -fx-background-

        // APPROACH #1 : Using Rectangle as shape
        Rectangle r = new Rectangle(30, 30);
        r.setArcHeight(radius);
        r.setArcWidth(radius);
        signUp.setShape(r);
        signUp.widthProperty().addListener(p -> r.setWidth(signUp.getWidth()));
        signUp.heightProperty().addListener(p -> r.setHeight(signUp.getHeight()));

        // APPROACH #2 : Using SVG path as shape
        //   signUp.widthProperty().addListener(p -> updateShape(signUp));
        //   signUp.heightProperty().addListener(p -> updateShape(signUp));

        StackPane root = new StackPane(signUp);
        root.setPadding(new Insets(10));
        Scene scene = new Scene(root, 300, 250);
        scene.getStylesheets().add(this.getClass().getResource("cssFile.css").toExternalForm());
        primaryStage.setTitle("BackgroundImage Radius");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void updateShape(StackPane signUp) {
        double r = 20; // BACKGROUND IMAGE RADIUS
        double w = signUp.getWidth();
        double h = signUp.getHeight();
        String s = "-fx-shape:\"M " + r + " 0 " +  //p1
                " L " + (w - r) + " " + "0" + //p2
                " Q " + w + " 0 " + w + " " + r + // p3,p4
                " L " + w + " " + (h - r) + //p5
                " Q " + w + " " + h + " " + (w - r) + " " + h + //p6,p7
                " L " + r + " " + h + //p8
                " Q 0 " + h + " 0 " + (h - r) + //p9,p10
                " L 0 " + r + //p11
                " Q 0 0 " + r + " 0 Z\";"; //p0,p1
        System.out.println(s);
        signUp.setStyle(s);
    }
}

enter image description here

Sai Dandem
  • 8,229
  • 11
  • 26
  • 1
    I think this might be more complicated than it needs be. Are you sure calling `updateShape` repeatedly is necessary? As I understand it, the shape should [be scaled to the size of the region](https://openjfx.io/javadoc/16/javafx.graphics/javafx/scene/layout/Region.html#scaleShapeProperty) by default. Also, it may be more readable to create a `Rectangle` (especially since each corner has the same radius) and then call `setShape` directly rather than using inline CSS, but that could just be preference. – Slaw May 26 '21 at 18:45
  • @Slaw, the method you mentioned will definitely work for square edge corners or if we are not bothered about the size of corner radius. I agree that the shape will scale to the size of the region, which will eventually scale the corner radius as well, making the node with inconsistent corner radius at different sizes. – Sai Dandem May 26 '21 at 21:31
  • Having said that, the other approach of setting the rectangle and updating it dimensions continuously works same as the one by building the path. Updated my code to include that approach as well. And as you said it is much cleaner ;P – Sai Dandem May 26 '21 at 21:41