我在StackPane中覆盖了两个图表(一个条形图和一个包含3个系列的折线图)。
折线图位于第一个栏的顶部,并在应用程序中正确显示。但是,当我尝试拍摄快照时,条形图不会显示。
我尝试拍摄该节点以及整个场景的快照,但是仍然没有显示。我想这与它是一个背景节点有关,但我似乎无法弄清楚如何使其显示。
WritableImage snapshot = stackPane.snapshot(new SnapshotParameters(),null);
ImageIO.write(SwingFXUtils.fromFXImage(snapshot,null),"png",new File("chart.png"));
我正在编辑以便添加其余代码:
控制器:
public class Controller {
@FXML StackPane stackPane;
public void onBtnClick(ActionEvent actionEvent) {
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
Graphs graphs = new Graphs();
StackPane secondaryStackpane = graphs.call();
stackPane.getChildren().addAll(secondaryStackpane.getChildren());
WritableImage snapshot = stackPane.snapshot(new SnapshotParameters(),null);
ImageIO.write(SwingFXUtils.fromFXImage(snapshot,null),"png",new File("chart.png"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
}
Graphs类:
public class Graphs extends Task {
StackPane stackPane;
NumberAxis yAxis;
NumberAxis yAxisRight;
CategoryAxis xAxis;
NumberAxis yAxisRightBlank;
public Graphs() {
stackPane = new StackPane();
xAxis = new CategoryAxis();
xAxis.setCategories(FXCollections.<String>observableArrayList("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"));
yAxis = new NumberAxis(0, 70, 10);
yAxisRight = new NumberAxis(0, 14, 1);
yAxisRightBlank = new NumberAxis(0, 15, 1);
yAxisRightBlank.setSide(Side.RIGHT);
xAxis.setLabel("Month");
yAxis.setLabel("Level");
yAxisRight.setLabel("Level (u)");
}
void createGraph() {
BarChart<String, Number> barChart = new BarChart<String, Number>(xAxis, yAxis);
barChart.setLegendVisible(false);
barChart.setAnimated(false);
barChart.getXAxis().setVisible(true);
barChart.getData().addAll(getAverageLoadPerFTE());
LineChart<String, Number> lineChartEffective = new LineChart<String, Number>(xAxis, yAxisRight);
lineChartEffective.setLegendVisible(false);
lineChartEffective.setAnimated(false);
lineChartEffective.setCreateSymbols(true);
lineChartEffective.setAlternativeRowFillVisible(false);
lineChartEffective.setAlternativeColumnFillVisible(false);
lineChartEffective.setHorizontalGridLinesVisible(false);
lineChartEffective.setVerticalGridLinesVisible(false);
lineChartEffective.getXAxis().setVisible(true);
lineChartEffective.getYAxis().setVisible(false);
lineChartEffective.getYAxis().setTickLabelsVisible(false);
lineChartEffective.getYAxis().setOpacity(0);
lineChartEffective.getData().addAll(getEffectiveCustomerSupport());
barChart.setAnimated(false);
barChart.applyCss();
barChart.layout();
lineChartEffective.setAnimated(false);
lineChartEffective.applyCss();
lineChartEffective.layout();
stackPane.getChildren().addAll(barChart, lineChartEffective);
}
public StackPane call() {
createGraph();
Platform.runLater(new Runnable() {
@Override
public void run() {
updateProgress(100, 100);
System.out.println("from call " + progressProperty());
}
});
return this.stackPane;
}
private XYChart.Series<String,Number> getEffectiveCustomerSupport() {
XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();
series.getData().add(new XYChart.Data<String,Number>("Jan", 2.9 ));
series.getData().add(new XYChart.Data<String,Number>("Feb", 2.7 ));
series.getData().add(new XYChart.Data<String,Number>("Mar", 3.3 ));
series.getData().add(new XYChart.Data<String,Number>("Apr", 3.4 ));
series.getData().add(new XYChart.Data<String,Number>("May", 3.3 ));
series.getData().add(new XYChart.Data<String,Number>("Jun", 3.2 ));
series.getData().add(new XYChart.Data<String,Number>("Jul", 3.3 ));
series.getData().add(new XYChart.Data<String,Number>("Aug", 4 ));
series.getData().add(new XYChart.Data<String,Number>("Sep", 3.8 ));
series.getData().add(new XYChart.Data<String,Number>("Oct", 4.1 ));
series.getData().add(new XYChart.Data<String,Number>("Nov", 0 ));
series.getData().add(new XYChart.Data<String,Number>("Dec", 0 ));
series.setName("Effective customer support");
return series;
}
private XYChart.Series<String,Number> getAverageLoadPerFTE() {
XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();
series.getData().add(new XYChart.Data<String,Number>("Jan", 58 ));
series.getData().add(new XYChart.Data<String,Number>("Feb", 54 ));
series.getData().add(new XYChart.Data<String,Number>("Mar", 47 ));
series.getData().add(new XYChart.Data<String,Number>("Apr", 34 ));
series.getData().add(new XYChart.Data<String,Number>("May", 33 ));
series.getData().add(new XYChart.Data<String,Number>("Jun", 32 ));
series.getData().add(new XYChart.Data<String,Number>("Jul", 30 ));
series.getData().add(new XYChart.Data<String,Number>("Aug", 36 ));
series.getData().add(new XYChart.Data<String,Number>("Sep", 29 ));
series.getData().add(new XYChart.Data<String,Number>("Oct", 33 ));
series.getData().add(new XYChart.Data<String,Number>("Nov", 0 ));
series.getData().add(new XYChart.Data<String,Number>("Dec", 0 ));
series.setName("Average load per FTE");
return series;
}
}
答案 0 :(得分:0)
这个问题本质上是重复的:
但是我将根据您问题中的代码提供一个答案,以便您可以更好地了解在特定情况下如何应用该答案。
基本上,主要问题是您没有将图形的背景色设置为透明色,因此当一个图表绘制在另一图表上时,后面的图表将不可见。这与快照例程无关,如果您只是尝试在场景中显示图表而不尝试对其进行快照,则图表将不会如您所愿的显示。
以下是使用以下更新的示例代码捕获的png:
Graphs.java
import javafx.collections.FXCollections;
import javafx.geometry.Side;
import javafx.scene.chart.*;
import javafx.scene.layout.StackPane;
public class Graphs {
private StackPane stackPane;
private NumberAxis yAxis;
private NumberAxis yAxisRight;
private CategoryAxis xAxis;
private NumberAxis yAxisRightBlank;
public Graphs() {
stackPane = new StackPane();
xAxis = new CategoryAxis();
xAxis.setCategories(FXCollections.observableArrayList(
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
));
yAxis = new NumberAxis(0, 70, 10);
yAxisRight = new NumberAxis(0, 14, 1);
yAxisRightBlank = new NumberAxis(0, 15, 1);
yAxisRightBlank.setSide(Side.RIGHT);
xAxis.setLabel("Month");
yAxis.setLabel("Level");
yAxisRight.setLabel("Level (u)");
}
StackPane createGraphs() {
BarChart<String, Number> barChart = new BarChart<>(xAxis, yAxis);
barChart.setLegendVisible(false);
barChart.setAnimated(false);
barChart.getXAxis().setVisible(true);
barChart.getData().addAll(getAverageLoadPerFTE());
LineChart<String, Number> lineChartEffective = new LineChart<>(xAxis, yAxisRight);
lineChartEffective.setLegendVisible(false);
lineChartEffective.setAnimated(false);
lineChartEffective.setCreateSymbols(true);
lineChartEffective.setAlternativeRowFillVisible(false);
lineChartEffective.setAlternativeColumnFillVisible(false);
lineChartEffective.setHorizontalGridLinesVisible(false);
lineChartEffective.setVerticalGridLinesVisible(false);
lineChartEffective.getXAxis().setVisible(true);
lineChartEffective.getYAxis().setVisible(false);
lineChartEffective.getYAxis().setTickLabelsVisible(false);
lineChartEffective.getYAxis().setOpacity(0);
lineChartEffective.getData().addAll(getEffectiveCustomerSupport());
stackPane.getStylesheets().addAll(getClass().getResource("overlay-chart.css").toExternalForm());
stackPane.getChildren().addAll(
barChart,
lineChartEffective
);
return stackPane;
}
private XYChart.Series<String, Number> getEffectiveCustomerSupport() {
XYChart.Series<String, Number> series = new XYChart.Series<>();
series.getData().add(new XYChart.Data<>("Jan", 2.9));
series.getData().add(new XYChart.Data<>("Feb", 2.7));
series.getData().add(new XYChart.Data<>("Mar", 3.3));
series.getData().add(new XYChart.Data<>("Apr", 3.4));
series.getData().add(new XYChart.Data<>("May", 3.3));
series.getData().add(new XYChart.Data<>("Jun", 3.2));
series.getData().add(new XYChart.Data<>("Jul", 3.3));
series.getData().add(new XYChart.Data<>("Aug", 4));
series.getData().add(new XYChart.Data<>("Sep", 3.8));
series.getData().add(new XYChart.Data<>("Oct", 4.1));
series.getData().add(new XYChart.Data<>("Nov", 0));
series.getData().add(new XYChart.Data<>("Dec", 0));
series.setName("Effective customer support");
return series;
}
private XYChart.Series<String, Number> getAverageLoadPerFTE() {
XYChart.Series<String, Number> series = new XYChart.Series<>();
series.getData().add(new XYChart.Data<>("Jan", 58));
series.getData().add(new XYChart.Data<>("Feb", 54));
series.getData().add(new XYChart.Data<>("Mar", 47));
series.getData().add(new XYChart.Data<>("Apr", 34));
series.getData().add(new XYChart.Data<>("May", 33));
series.getData().add(new XYChart.Data<>("Jun", 32));
series.getData().add(new XYChart.Data<>("Jul", 30));
series.getData().add(new XYChart.Data<>("Aug", 36));
series.getData().add(new XYChart.Data<>("Sep", 29));
series.getData().add(new XYChart.Data<>("Oct", 33));
series.getData().add(new XYChart.Data<>("Nov", 0));
series.getData().add(new XYChart.Data<>("Dec", 0));
series.setName("Average load per FTE");
return series;
}
}
GraphsApp.java
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.io.File;
public class GraphsApp extends Application {
@Override
public void start(Stage stage) throws Exception {
Graphs graphs = new Graphs();
Pane graphPane = graphs.createGraphs();
stage.setScene(new Scene(graphPane));
stage.show();
WritableImage snapshot = graphPane.snapshot(new SnapshotParameters(),null);
File graphFile = new File("chart.png");
ImageIO.write(
SwingFXUtils.fromFXImage(snapshot,null),
"png",
graphFile
);
System.out.println("Wrote: " + graphFile.getAbsolutePath());
}
public static void main(String[] args) {
launch(args);
}
}
overlay-chart.css
该文件的生成目录应与Graphs
Java类的类文件位于同一生成目录。
/** file: overlay-chart.css (place in same directory as LayeredXyChartsSample */
.chart-plot-background {
-fx-background-color: transparent;
}
.default-color0.chart-series-line {
-fx-stroke: forestgreen;
}
您的代码有很多奇怪的东西,涉及JavaFX Task
和Platform.runLater
调用。对于这样的任务,不需要或不需要调用JavaFX并发结构,因此我删除了所有这些。
此外,当要求提供mcve时,请提供一些极少的内容(例如,如果不需要它来复制问题,则不要使用FXML)并且要完整,以供将来参考。只需复制并粘贴即可运行,而不必花时间进行修改,而只是试图复制问题。
请注意,使用我提供的更新代码,它现在可以绘制和快照堆积的图表,但是,我不知道它实际上是否按照您希望的那样绘制图表。例如,每个图表相对于彼此的x轴或y轴的比例和范围可能不如您希望的相对,因此,图表可能会或可能不会以对您的组合数据系列“正确”的方式绘制。如果不正确,则需要分别解决这些问题。