I have a simple LineChart, that opens in a new window on press of a button. This LineChart uses an image stored on harddrive as its background. If I close the window countaining the LineChart, change the image file (or delete it) and reopen the window, the old image is loaded again. I disabled the cache of my LineChart in Scene Builder and in my code, but it doesn't help.
Can somebody give me a hint what I'm missing?
Here's a simple code-snippet of the LineChart-Controller that I'm using for testing:
@FXML
private LineChart<?, ?> lineChart;
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
lineChart.setCache(false);
Node chartNode = lineChart.lookup(".chart-plot-background");
chartNode.setCache(false);
chartNode.setStyle("-fx-background-image: url('file:///C://Temp//histData.png'); -fx-background-position: center center;");
}
Thanks!
----- Update ----- Currently I'm using a StackPane with an ImageView and LineChart to display my image. But initial problem remains. Once an external image is loaded by css, the same image is shown, even if the file itself changed.
Here is my updated testcase, loaded as a dialog when pressing a button.
FXML:
<?import javafx.scene.image.*?>
<?import javafx.scene.chart.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" cacheShape="false" prefHeight="500.0" prefWidth="812.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chartbackgroundtest.ChartController">
<children>
<LineChart fx:id="lineChart" cacheShape="false" prefHeight="353.0" prefWidth="611.0" styleClass="mychart">
<xAxis>
<CategoryAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
</children>
</AnchorPane>
Controller: package chartbackgroundtest;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.chart.LineChart;
public class ChartController implements Initializable {
@FXML
private LineChart<?, ?> lineChart;
Node chartNode;
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
chartNode = lineChart.lookup(".chart-plot-background");
lineChart.getStylesheets().clear();
chartNode.setStyle(null);
chartNode.setStyle("-fx-background-image: url('file:///C://Temp//histData.png'); -fx-background-position: center;");
new File("C:\\Temp\\histData.png").renameTo(new File("C:\\Temp\\histData3.png"));
new File("C:\\Temp\\histData2.png").renameTo(new File("C:\\Temp\\histData.png"));
new File("C:\\Temp\\histData3.png").renameTo(new File("C:\\Temp\\histData2.png"));
chartNode.applyCss();
lineChart.requestLayout();
}
}
I have two different images, histData.png and histData2.png. My chart uses histData.png as the background-image of the chart-plot-background. After opening the dialog, the files histData.png and histData2.png are switched. Closing the dialog and re-opening it by pressing the assigned button, the original image is still loaded.
Code of the button, opening the dialog:
@FXML
private void handleButtonAction(ActionEvent event) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Chart.fxml"));
loader.setBuilderFactory(new JavaFXBuilderFactory());
Stage dialog = new Stage();
dialog.initStyle(StageStyle.UTILITY);
dialog.initModality(Modality.APPLICATION_MODAL);
try {
Scene scene = new Scene(loader.load());
dialog.setScene(scene);
dialog.show();
} catch (IOException ex) {
Logger.getLogger(MainViewController.class.getName()).log(Level.SEVERE, null, ex);
}
}
I recommend you saving file with the different name and call to setStyle with different name.
I suggest you watch the background image file for changes, then if the file changes, set the background image to null, then set the background image back to the file again to force a reload. See: Can I watch for single file change with WatchService (not the whole directory)?.
The setCache function disables the JavaFX system from caching of a node as image in memory for performance reasons; i.e. when setCache is on, it hints to JavaFX to renders the node once then store it in a cached image. I'm not sure if JavaFX has a seperate cache for images loaded via styles or not. If it does and that causes my previous suggestion not to work, you could instead place your chart in a StackPane with the Chart on top and an ImageView for the background view behind the Chart, then load a new Image when the file watcher detects that the image file has changed (thereby bypassing any caching mechanism that JavaFX CSS system may or may not have).