Saw*_*yer 8 java javafx javafx-2 javafx-8
我只想从JavaFX图表API生成图表图像.我不想显示应用程序窗口,也不想启动应用程序(如果没有必要).
public class LineChartSample extends Application {
private List<Integer> data;
@Override public void start(Stage stage) {
stage.setTitle("Line Chart Sample");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Month");
final LineChart<String,Number> lineChart =
new LineChart<String,Number>(xAxis,yAxis);
lineChart.setTitle("Stock Monitoring, 2010");
XYChart.Series series = new XYChart.Series();
series.setName("My portfolio");
series.getData().add(new XYChart.Data("Jan", 23));
series.getData().add(new XYChart.Data("Feb", 14));
Scene scene = new Scene(lineChart,800,600);
lineChart.getData().add(series);
WritableImage image = scene.snapshot(null);
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", chartFile);
//stage.setScene(scene);
//stage.show();
}
public static void main(String[] args) {
launch(args);
}
public setData(List<Integer> data) {this.data = data;}
}
Run Code Online (Sandbox Code Playgroud)
在start方法中,我实际上需要访问外部数据以构建系列数据,但似乎没有办法从start方法访问外部数据,如果我将数据存储在成员变量中data,则在开始时它为null调用.我实际上并不关心舞台和场景对象,只要图表图像可以渲染,我该如何解决问题呢?我想构建一个可以使用输入数据调用的API,并使用数据绘制图表,然后返回该文件.
public File toLineChart(List<Integer> data) {
...
}
Run Code Online (Sandbox Code Playgroud)
您不需要显示Stage但Node必须附加到a Scene.来自以下文件snapshot:
注意:为了使CSS和布局正常工作,节点必须是场景的一部分(场景可以附加到舞台,但不必是).
修改a的一个限制Scene是,它必须在J avaFX Application Thread上发生,它必须具有必须初始化JavaFX Toolkit的先决条件.
可以通过扩展方法为您执行此操作的Application类来完成初始化launch,或者作为一种解决方法,您可以JFXPanel在Swing Event Dispatcher Thread上创建新实例.
如果您正在扩展Application并在start方法中执行某些代码,则确保此代码将在JavaFX Application Thread上执行,否则您可以使用Platform.runLater(...)从不同线程调用的块来确保相同.
这是一个可能的例子:
该类提供了一种静态方法,用于将图表绘制到文件中,并返回File或者null创建是否成功.
在此方法中,通过在Swing EDT上创建JavaFX Toolkit来初始化,然后创建图表来完成JavaFX Application Thread.在该方法中使用两个布尔值来存储操作完成并成功.JFXPanel
在completed标志切换为true之前,该方法不会返回.
注意:这个实际上只是一个(工作)示例,可以进行很多改进.
public class JavaFXPlotter {
public static File toLineChart(String title, String seriesName, List<Integer> times, List<Integer> data) {
File chartFile = new File("D:\\charttest.png");
// results: {completed, successful}
Boolean[] results = new Boolean[] { false, false };
SwingUtilities.invokeLater(() -> {
// Initialize FX Toolkit
new JFXPanel();
Platform.runLater(() -> {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
lineChart.setTitle(title);
XYChart.Series<Number, Number> series = new XYChart.Series<>();
series.setName(seriesName);
for (int i = 0; i < times.size(); i++)
series.getData().add(new XYChart.Data<Number, Number>(times.get(i), data.get(i)));
lineChart.getData().add(series);
Scene scene = new Scene(lineChart, 800, 600);
WritableImage image = scene.snapshot(null);
try {
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", chartFile);
results[1] = true;
} catch (Exception e) {
results[0] = true;
} finally {
results[0] = true;
}
});
});
while (!results[0]) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return (results[1]) ? chartFile : null;
}
}
Run Code Online (Sandbox Code Playgroud)
以及可能的用法
List<Integer> times = Arrays.asList(new Integer[] { 0, 1, 2, 3, 4, 5 });
List<Integer> data = Arrays.asList(new Integer[] { 4, 1, 5, 3, 0, 7 });
File lineChart = JavaFXPlotter.toLineChart("Sample", "Some sample data", times, data);
if (lineChart != null)
System.out.println("Image generation is done! Path: " + lineChart.getAbsolutePath());
else
System.out.println("File creation failed!");
System.exit(0);
Run Code Online (Sandbox Code Playgroud)
和生成的图片(charttest.png)
| 归档时间: |
|
| 查看次数: |
2027 次 |
| 最近记录: |