我想创建一个简单的方法,绘制折线图,给出一个包含要显示的点的对象和一些其他图表属性(如图表标题),并将其保存为图像。
这是一个代码示例:
public class MyChartApp {
public static void main(String[] args) throws IOException {
ChartData chartData = generateChartData();
WritableImage image = constructChartImage(chartData);
save(image, "chart.png");
}
public static WritableImage constructChartImage(ChartData data) {
// code to be written
}
private static ChartData generateChartData() {
ChartData chartData = new ChartData();
chartData.setValuesX(new double[]{1,2,3,4,5,6,7,8,9});
chartData.setValuesY(new double[]{9,8,7,6,5,4,3,2,1});
chartData.setChartTitle("My Chart");
return chartData;
}
public static void save(WritableImage image, String path) throws IOException {
BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
ImageIO.write(bImage, "png", new File(path));
}
/**
* JavaFX application used to construct the chart.
*/
public static class MyChart extends Application {
@Override
public void start(Stage stage) throws Exception {
// Somehow retrieve chartData passed to constructChartImage()
ChartData chartData = ...
//defining the axes
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
//creating the chart
final LineChart<Number,Number> lineChart =
new LineChart<>(xAxis,yAxis);
lineChart.setAnimated(false);
lineChart.setTitle(chartData.getChartTitle());
//defining a series
XYChart.Series series = new XYChart.Series();
//populating the series with data
addAll(series, chartData);
Scene scene = new Scene(lineChart,800,600);
lineChart.getData().add(series);
lineChart.applyCss();
lineChart.layout();
stage.setScene(scene);
WritableImage image = scene.snapshot(null);
// somehow pass the image object to constructChartImage().
}
// utility methods for adding data to the chart //
private static void addAll(XYChart.Series series, ChartData chartData) {
double[] valuesX = chartData.getValuesX();
double[] valuesY = chartData.getValuesY();
for (int i = 0; i < valuesX.length; i++) {
add(series, valuesX[i], valuesY[i]);
}
}
private static void add(XYChart.Series series, double x, double y) {
series.getData().add(new XYChart.Data(x,y));
}
}
public static class ChartData {
private double[] valuesX;
private double[] valuesY;
private String chartTitle;
public String getChartTitle() {
return chartTitle;
}
public void setChartTitle(String chartTitle) {
this.chartTitle = chartTitle;
}
public double[] getValuesX() {
return valuesX;
}
public void setValuesX(double[] valuesX) {
this.valuesX = valuesX;
}
public double[] getValuesY() {
return valuesY;
}
public void setValuesY(double[] valuesY) {
this.valuesY = valuesY;
}
}
}
虽然这个想法可能看似简单,但实施却并非如此。我不知道如何将图表数据从主应用程序传递到JavaFX应用程序。在JavaFX线程内生成数据(例如,使用generateChartData()
方法)不是首选解决方案。
有一个类似的问题here,但建议的解决方案对我没有用。它还使用静态共享字段,我认为这不是一个好习惯。另外,我的情况比较简单,因为我不希望随时更新数据。
有什么想法吗?
答案 0 :(得分:1)
如果目的只是创建一个图表并将其保存到图像文件中,那么为什么不这么做呢
public class MyChartApp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
// other app code...
MyChart myChart = new MyChart();
ChartData chartData = myChart.generateChartData();
WritableImage image = myChart.constructChartImage(chartData);
myChart.save(image, "chart.png");
// other app code...
}
public static class MyChart {
public WritableImage constructChartImage(ChartData data) {
//defining the axes
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
//creating the chart
final LineChart<Number,Number> lineChart =
new LineChart<>(xAxis,yAxis);
lineChart.setAnimated(false);
lineChart.setTitle(chartData.getChartTitle());
//defining a series
XYChart.Series series = new XYChart.Series();
//populating the series with data
addAll(series, chartData);
Scene scene = new Scene(lineChart,800,600);
lineChart.getData().add(series);
lineChart.applyCss();
lineChart.layout();
WritableImage image = scene.snapshot(null);
return image ;
}
private ChartData generateChartData() {
ChartData chartData = new ChartData();
chartData.setValuesX(new double[]{1,2,3,4,5,6,7,8,9});
chartData.setValuesY(new double[]{9,8,7,6,5,4,3,2,1});
chartData.setChartTitle("My Chart");
return chartData;
}
public void save(WritableImage image, String path) throws IOException {
BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
ImageIO.write(bImage, "png", new File(path));
}
private void addAll(XYChart.Series series, ChartData chartData) {
double[] valuesX = chartData.getValuesX();
double[] valuesY = chartData.getValuesX();
for (int i = 0; i < valuesX.length; i++) {
add(series, valuesX[i], valuesY[i]);
}
}
private void add(XYChart.Series series, double x, double y) {
series.getData().add(new XYChart.Data(x,y));
}
}
public static class ChartData {
private double[] valuesX;
private double[] valuesY;
private String chartTitle;
public String getChartTitle() {
return chartTitle;
}
public void setChartTitle(String chartTitle) {
this.chartTitle = chartTitle;
}
public double[] getValuesX() {
return valuesX;
}
public void setValuesX(double[] valuesX) {
this.valuesX = valuesX;
}
public double[] getValuesY() {
return valuesY;
}
public void setValuesY(double[] valuesY) {
this.valuesY = valuesY;
}
}
}