0

What i want to achieve:

I am using a FileChooser and the user selects an appropriate .jpg image file . Then i am copying that image , renaming it background.jpg to a known folder and trying to set it as the background image of the application using .setStyle(...); There is not problem of copying the image [ i am checking it]


The Problem that occurs:

I have a Stage with a BorderPane . The BorderPane has an background Image , i do that using

 borderPane.setStyle("-fx-background-image:url('filepath')");

!It works well the first time!

->Then i am deleting that file [background.jpg] and i am replacing it with another file named also [background.jpg] . The background image of the BorderPane isn't changing ....

I have tried also resetting the same style using again :

  borderPane.setStyle("-fx-background-image:url('filepath')");

Finally when i am changing the filename , for example to [background-12.jpg] and reseting the style using the above it changes the background image.


Which exactly is the problem ? I mean i am sure that the background.jpg has been created , i am checking it and also when i am changing the name to something other again and again it works .

Is the Java CSS Parser lazy to parse the new style which is the same but has other -fx-background-image resource ?

As for the File path i am sure it is well , i am using the code below :

//Maou is the File URL in appropriate format for CSS
String maou = file.getAbsoluteFile().toURI().toString()

//Here i add the appropriate file separator, if not JavaFX will report error
maou = maou.replaceAll("\\Q\\\\E", "//"); 

//Print maou
System.out.println("Maou=\n" + maou);


Solution :

I found as best solution using James_D answer , a little bit modified so it covers the whole window:

BackgroundImage bgImg = new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT,
        new BackgroundSize(window.getWidth(), window.getHeight(), true, true, true, true));
GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93
  • Interestingly, [this question](http://stackoverflow.com/questions/27962287/disable-caching-of-javafx-chart-background-image) is an almost exact duplicate of yours. The suggestions were to use a StackPane and ImageView (hah) or to rename the image. – Michael Apr 25 '17 at 15:43
  • @Michael I have started adding this extra code for `ImageView` and it's bindings to `StackPane` `Width` and `Height` :) . Although i have found a different approach , first renaming the image , adding the style and then renaming it again Oulala :) – GOXR3PLUS Apr 25 '17 at 15:45
  • If you find a solution which works well, don't be afraid to leave an answer to your own question. – Michael Apr 25 '17 at 15:50

2 Answers2

2

Rather than using an inline style, I would recommend setting the background via the background property directly:

Image img = new Image(file.getAbsoluteFile().toURI().toString());
BackgroundImage bgImg = new BackgroundImage(img, 
    BackgroundRepeat.NO_REPEAT,
    BackgroundRepeat.NO_REPEAT,
    BackgroundPosition.DEFAULT,
    BackgroundSize.DEFAULT);
borderPane.setBackground(new Background(bgImg));

The Background class provides Java API programmatic access to all the same properties that can be set by CSS.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • Sorry: copy and paste error. Note that it's possible (but probably unlikely) this suffers from the same caching problem: I haven't tested. – James_D Apr 25 '17 at 15:54
  • Eclipse is reporting `The constructor BackgroundImage(Image, BackgroundRepeat, BackgroundRepeat, BackgroundPosition, double) is undefined` , triple checked the imports . Instead replacing `BackgroundSize.AUTO` with `BackgroundSize.DEFAULT` works . – GOXR3PLUS Apr 25 '17 at 16:08
  • 1
    Oh: `BackgroundSize.AUTO` is a `double`. That's kind of weird. Edited (again). Ohhh... I see, you're supposed to use it to pass as the value for one dimension when you specify value for the other dimension, to preserve ratio. Yeah, use `DEFAULT` instead. – James_D Apr 25 '17 at 16:09
  • Thanks for the answer it seems to work pretty well :) ! I used a modified version cause i wanted the image to cover the entire area of the `BorderPane`. I added this on my question . – GOXR3PLUS Apr 25 '17 at 16:42
1

While I don't know exactly what's going on, presumably it's some form of caching which JavaFX is doing to try to be "helpful". I may look into the source code later.

To be honest, though, setting a background via CSS feels like the wrong approach to me. I always avoid setting any styles explicitly, like:

borderPane.setStyle("something");

and prefer to add and remove style classes:

borderPane.getStyleClass().add("foo");
borderPane.getStyleClass().remove("foo");

I don't think this is possible in your situation, so I would instead use a StackPane to layer your content over an ImageView.

ImageView img = new ImageView(new Image(new URL("path")));
StackPane stack = new StackPane();
stack.getChildren.addAll(img, /*overlaid content*/);
Michael
  • 41,989
  • 11
  • 82
  • 128
  • Thanks for the recomendation of `ImageView` , i prefer to keep `.setStyle(..)` if it is possible . I need to know why it happens :) – GOXR3PLUS Apr 25 '17 at 15:36
  • Hm, I think that's the wrong approach. You've already seen that it *doesn't* work. *Why* is almost irrelevant. – Michael Apr 25 '17 at 15:38
  • 2
    Instead of modifying the scene graph by adding a `StackPane`, I would think the preferred method of setting the background programatically would be to use [`setBackground`](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Region.html#setBackground-javafx.scene.layout.Background-): `borderPane.setBackground(new Background(new BackgroundImage(new Image(url),...)));` – James_D Apr 25 '17 at 15:46
  • I used the answer of `James_D` , easier to implement and it works well :) – GOXR3PLUS Apr 25 '17 at 16:42
  • No problem. Glad you got it sorted. – Michael Apr 25 '17 at 17:47