Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8093843

Chart axis and legend not visible when printing

XMLWordPrintable

      In JavaFX 8, when using the print API and printing a LineChart offscreen (a copy of a chart that is visible on the app's stage), both chart's axis are blank despite been set to no animation. The chart legend is also missing though empty space is present where it should be visible. See following code that demonstrate the issue.

      package test;

      import java.util.LinkedList;
      import java.util.List;
      import javafx.application.Application;
      import javafx.collections.FXCollections;
      import javafx.event.ActionEvent;
      import javafx.event.EventHandler;
      import javafx.geometry.Side;
      import javafx.print.JobSettings;
      import javafx.print.PageLayout;
      import javafx.print.PrinterJob;
      import javafx.scene.Scene;
      import javafx.scene.chart.LineChart;
      import javafx.scene.chart.NumberAxis;
      import javafx.scene.control.Button;
      import javafx.scene.control.ToolBar;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;

      /**
       *
       * @author fabriceb
       */
      public class Main extends Application {

          @Override
          public void start(Stage primaryStage) {
              final int minX = 0;
              final int maxX = 11;
              double minY = Integer.MAX_VALUE;
              double maxY = Integer.MIN_VALUE;
              final List<LineChart.Data> dataList = new LinkedList<>();
              for (int i = minX; i < maxX; i++) {
                  final double y = Math.pow(i, 2);
                  minY = Math.min(minY, y);
                  maxY = Math.max(maxY, y);
                  final LineChart.Data data = new LineChart.Data<>(i, y);
                  dataList.add(data);
              }
              final NumberAxis xAxis = new NumberAxis("x", minX, maxX, (maxX - minX) / 5);
              final NumberAxis yAxis = new NumberAxis("y = x ^ 2", minY, maxY, (maxY - minY) / 5);
              final LineChart.Series series = new LineChart.Series("Power of 2", FXCollections.observableList(dataList));
              final LineChart lineChart = new LineChart(xAxis, yAxis, FXCollections.observableArrayList(series));
              lineChart.setTitle("Chart printing example");
              lineChart.setLegendVisible(true);
              lineChart.setLegendSide(Side.RIGHT);
              final Button printButton = new Button("Print");
              // Not supported by NetBeans 7.3 yet.
      // printButton.setOnAction(actionEvent -> printChart(lineChart));
              printButton.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(ActionEvent t) {
                      printChart(lineChart);
                  }
              });
              final ToolBar toolBar = new ToolBar();
              toolBar.getItems().add(printButton);
              final BorderPane root = new BorderPane();
              root.setTop(toolBar);
              root.setCenter(lineChart);
              final Scene scene = new Scene(root, 500, 500);
              primaryStage.setTitle("Test Printing");
              primaryStage.setScene(scene);
              primaryStage.show();
          }

          private LineChart.Data copyData(final LineChart.Data sourceData) {
              final LineChart.Data result = new LineChart.Data(sourceData.getXValue(), sourceData.getYValue());
              return result;
          }

          private LineChart.Series copySeries(final LineChart.Series sourceSeries) {
              final String name = sourceSeries.getName();
              final List<LineChart.Data> dataList = new LinkedList<>();
              for (Object d : sourceSeries.getData()) {
                  final LineChart.Data sourceData = (LineChart.Data) d;
                  final LineChart.Data data = copyData(sourceData);
                  dataList.add(data);
              }
              LineChart.Series result = new LineChart.Series(name, FXCollections.observableList(dataList));
              return result;
          }

          private NumberAxis copyAxis(final NumberAxis sourceAxis) {
              final String label = sourceAxis.getLabel();
              final double lowerBound = sourceAxis.getLowerBound();
              final double upperBound = sourceAxis.getUpperBound();
              final double tickUnit = sourceAxis.getTickUnit();
              NumberAxis result = new NumberAxis(label, lowerBound, upperBound, tickUnit);
              return result;
          }

          private LineChart copyChart(final LineChart sourceChart) {
              final List<LineChart.Series> seriesList = new LinkedList<>();
              for (Object s : sourceChart.getData()) {
                  final LineChart.Series sourceSeries = (LineChart.Series) s;
                  final LineChart.Series series = copySeries(sourceSeries);
                  seriesList.add(series);
              }
              NumberAxis xAxis = copyAxis((NumberAxis) sourceChart.getXAxis());
              NumberAxis yAxis = copyAxis((NumberAxis) sourceChart.getYAxis());
              LineChart result = new LineChart(xAxis, yAxis, FXCollections.observableList(seriesList));
              result.setTitle(sourceChart.getTitle());
              result.setLegendVisible(sourceChart.isLegendVisible());
              result.setLegendSide(sourceChart.getLegendSide());
              return result;
          }

          private void printChart(final LineChart sourceChart) {
              final LineChart chartCopy = copyChart(sourceChart);
              chartCopy.setAnimated(false);
              chartCopy.getXAxis().setAnimated(false);
              chartCopy.getYAxis().setAnimated(false);
              final PrinterJob printerJob = PrinterJob.createPrinterJob();
              if (printerJob.showPrintDialog(sourceChart.getScene().getWindow())) {
                  final JobSettings settings = printerJob.getJobSettings();
                  final PageLayout pageLayout = settings.getPageLayout();
                  final double pageWidth = pageLayout.getPrintableWidth();
                  final double pageHeight = pageLayout.getPrintableHeight();
                  chartCopy.setPrefSize(pageWidth, pageHeight);
                  if (printerJob.printPage(chartCopy)) {
                      printerJob.endJob();
                  }
              }
          }

          /**
           * The main() method is ignored in correctly deployed JavaFX
           * application. main() serves only as fallback in case the
           * application can not be launched through deployment artifacts,
           * e.g., in IDEs with limited FX support. NetBeans ignores main().
           * @param args the command line arguments
           */
          public static void main(String[] args) {
              launch(args);
          }
      }


      When printed, both axis show no legend, and both axis content is empty.

            prr Philip Race
            fbouyajfx Fabrice Bouyé (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: