I want to create a JavaFx chart factory. In this (How to get an image file from a Javafx chart(linechart) without actually rendering it?) thread I posted a question about generating chart wihtout actually renderingon an FX application window. But now that I want to implement the solution multiple times I get the "Exception in thread "main" java.lang.IllegalStateException: Application launch must not be called more than once" exception.
I use two classes. StartChartsFx class has the main non FX thread, from here I create the data and trigger the chart creation process. ChartFactory class launches the FX thread and generates the png charts.
This is the StartChartsFx class:
public class StartChartsFx {
public static void main(String[] args) {
// It can be run just once ChartFactory chf=new ChartFactory();
HashMap<Number, Number> xyData=new HashMap<>();
xyData.put(1, 23);
xyData.put(2, 14);
xyData.put(3, 15);
xyData.put(4, 24);
xyData.put(5, 34);
xyData.put(6, 36);
xyData.put(7, 22);
xyData.put(8, 45);
xyData.put(9, 43);
xyData.put(10, 17);
xyData.put(11, 29);
xyData.put(12, 25);
ChartFactory chf=new ChartFactory();
chf.execute(xyData);
chf.execute(xyData);
System.out.print("Done");
}
}
This is the ChartFactory class:
public class ChartFactory extends Application {
@Override
public void stop() throws Exception {
super.stop();
Platform.exit();
}
private static HashMap<Number, Number> a;
@Override
public void start(Stage arg0) throws Exception {
Platform.setImplicitExit(false);
// defining the axes
NumberAxis xAxis = new NumberAxis();
NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Number of Month");
// creating the chart
LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
lineChart.setTitle("Stock Monitoring, 2010");
lineChart.setAnimated(false);
// defining a series
XYChart.Series<Number, Number> series = new XYChart.Series<>();
series.setName("My portfolio");
// populating the series with data
for(Map.Entry<Number, Number> entry:a.entrySet() )
series.getData().add(new XYChart.Data<Number, Number>(entry.getKey(), entry.getValue()));
lineChart.getData().add(series);
lineChart.setPrefSize(800, 240);
Scene scene = new Scene(lineChart, 800, 240);
System.out.println(System.getProperty("user.dir"));
String element = getClass().getResource("chartStyles.css").toExternalForm();
scene.getStylesheets().add(element);
WritableImage wi = lineChart.snapshot(new SnapshotParameters(), new WritableImage(800, 240));
File file = new File("CanvasImage.png");
try {
ImageIO.write(SwingFXUtils.fromFXImage(wi, null), "png", file);
} catch (Exception s) {
}
CategoryAxis xAxis2 = new CategoryAxis();
xAxis2.setLabel("Devices");
NumberAxis yAxis2 = new NumberAxis();
yAxis2.setLabel("Visits");
BarChart<String, Number> barChart = new BarChart<>(xAxis2, yAxis2);
barChart.setAnimated(false);
XYChart.Series<String, Number> dataSeries1 = new XYChart.Series<>();
dataSeries1.setName("2014");
dataSeries1.getData().add(new XYChart.Data<String, Number>("Desktop", 178));
dataSeries1.getData().add(new XYChart.Data<String, Number>("Phone", 65));
dataSeries1.getData().add(new XYChart.Data<String, Number>("Tablet", 23));
barChart.getData().add(dataSeries1);
barChart.setPrefSize(640, 480);
scene = new Scene(barChart, 640, 480);
scene.getStylesheets().add(getClass().getResource("chartStyles.css").toExternalForm());
wi = barChart.snapshot(new SnapshotParameters(), new WritableImage(640, 480));
file = new File("Canvas2Image.png");
try {
ImageIO.write(SwingFXUtils.fromFXImage(wi, null), "png", file);
} catch (Exception s) {
}
System.out.print("Done!");
Platform.exit();
}
public void execute(HashMap<Number, Number> xyData) {
a = xyData;
launch();
}
}
I'd like to generate charts with different datasets an undetermined amount of times, but it runs only once.