This discussion is archived
9 Replies Latest reply: Jun 18, 2013 7:00 PM by 098a562b-359e-426b-b5e4-87df2c759fb4 RSS

headless LineChart?

098a562b-359e-426b-b5e4-87df2c759fb4 Newbie
Currently Being Moderated

How do you create a LineChart and write the chart to a file (e.g. PNG file) without a GUI, i.e. for X11 the DISPLAY environment variable is unset and for OSX a GUI does not pop up? I have tried to achieve this using an early access version of Java 8, but so far, no luck. I attempt to create a chart (without an Application) like:

 

        final NumberAxis xAxis = new NumberAxis();

        final NumberAxis yAxis = new NumberAxis();

        final LineChart<Number,Number> lineChart = new LineChart<Number,Number>(xAxis,yAxis);

 

but I get the following exception when trying to allocate the 'xAxis'.

 

Thanks very much for any suggestions...

 

Exception in thread "main" java.lang.ExceptionInInitializerError

        at javafx.scene.chart.Axis.<init>(Axis.java:85)

        at javafx.scene.chart.ValueAxis.<init>(ValueAxis.java:249)

        at javafx.scene.chart.NumberAxis.<init>(NumberAxis.java:142)

        at LineChartSample.<init>(LineChartSample.java:31)

        at LineChartSample.main(LineChartSample.java:88)

Caused by: java.lang.NullPointerException

        at com.sun.javafx.tk.quantum.QuantumToolkit.isSupported(QuantumToolkit.java:1261)

        at com.sun.javafx.application.PlatformImpl.isSupported(PlatformImpl.java:452)

        at com.sun.javafx.application.PlatformImpl$11.run(PlatformImpl.java:548)

        at java.security.AccessController.doPrivileged(Native Method)

        at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:544)

        at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:479)

        at javafx.scene.control.Control.<clinit>(Control.java:81)

        ... 5 more

  • 1. Re: headless LineChart?
    KonradZuse Explorer
    Currently Being Moderated

    Your line chart isn't correct, as you see you get some exceptions.

     

     

    My code works fine

     

    NumberAxis xAxis = new NumberAxis("Number saved", 1, 10.1, 1);

       

        NumberAxis yAxis = new NumberAxis("Calculated Value", 0, 1000, 1);

        LineChart chart = new LineChart(xAxis, yAxis);    

    XYChart.Series<Double,Double> volts = new XYChart.Series<>();

    XYChart.Series<Double,Double> ress = new XYChart.Series<>();

    XYChart.Series<Double,Double> curs = new XYChart.Series<>();

    XYChart.Series<Double,Double> pows = new XYChart.Series<>();

     

                   

                  

                       

               chart.getData().add(volts);

               chart.getData().add(ress);

               chart.getData().add(curs);

               chart.getData().add(pows);

              

               volts.setName("Voltage");

               ress.setName("Resistance");

               curs.setName("Current");

               pows.setName("Power");

              

               Scene scene = new Scene(root);

               scene.getStylesheets().add("calculator/chart.css");

              

               chart.getStyleClass().add("lineChart");

                           fxContainer.setScene(scene);

                           graph.add(fxContainer);

                           start = true;

     

    root.getChildren().add(chart);// you wouldn't add this.

     

    You might not need a lot of this if you're not going to visually create it, but things like "name" can be used for identification purposes.

  • 2. Re: headless LineChart?
    jsmith Guru
    Currently Being Moderated

    I don't think JavaFX operation in a headless environment is currently supported by the public API.

     

    You could file a feature request for such support against the JavaFX runtime project in the JavaFX issue tracker:

    https://javafx-jira.kenai.com/

     

    There is sample code for rendering charts in this thread:

    https://forums.oracle.com/thread/2462410

     

    The sample code is for rendering hundreds of charts, so it could be done much simpler if you just have a couple of charts and don't require all of the asynchronous processing (which is likely).

     

    Basically, you render the chart with chart animation turned off, take a snapshot of the chart with node.snapshot, convert the snapshot image to a swing buffered image with SwingFXUtils, then use imageio to render the resultant chart to an image file such as a png.  And (as far as I am aware) you need to do it all in a headful environment.

  • 3. Re: headless LineChart?
    098a562b-359e-426b-b5e4-87df2c759fb4 Newbie
    Currently Being Moderated

    Thank you very much for your reply! I thought no one would be willing to help...

     

    I'm trying to create the LineChart without using the Application class since I cannot find a way to create an Application object without the GUI appearing... So I took your example and added it to my simple test; below is my example with the command line commands in bold and the output in italics. If you have any more suggestions, please let me know, and thank you for your reply!

     

    bash$ cat -n HeadlessChart.java

         1 import javafx.scene.chart.NumberAxis;

         2 import javafx.scene.chart.LineChart;

         3

         4 public class HeadlessChart {

         5 

         6    public HeadlessChart( ) {

         7        NumberAxis xAxis = new NumberAxis("Number saved", 1, 10.1, 1);

         8        NumberAxis yAxis = new NumberAxis("Calculated Value", 0, 1000, 1);

         9

        10        LineChart<Number,Number> chart = new LineChart<Number,Number>(xAxis, yAxis);   

        11    }

        12    public static void main(String[] args) {

        13        final HeadlessChart sample = new HeadlessChart( );

        14    }

        15 }

    bash$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java -version

    java version "1.8.0-ea"

    Java(TM) SE Runtime Environment (build 1.8.0-ea-b93)

    Java HotSpot(TM) 64-Bit Server VM (build 25.0-b34, mixed mode)

    bash$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/javac -Xlint:unchecked HeadlessChart.java

    bash$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java HeadlessChart

    Exception in thread "main" java.lang.ExceptionInInitializerError

      at javafx.scene.chart.Axis.<init>(Axis.java:85)

      at javafx.scene.chart.ValueAxis.<init>(ValueAxis.java:249)

      at javafx.scene.chart.ValueAxis.<init>(ValueAxis.java:261)

      at javafx.scene.chart.NumberAxis.<init>(NumberAxis.java:165)

      at HeadlessChart.<init>(HeadlessChart.java:7)

      at HeadlessChart.main(HeadlessChart.java:13)

    Caused by: java.lang.NullPointerException

      at com.sun.javafx.tk.quantum.QuantumToolkit.isSupported(QuantumToolkit.java:1261)

      at com.sun.javafx.application.PlatformImpl.isSupported(PlatformImpl.java:452)

      at com.sun.javafx.application.PlatformImpl$11.run(PlatformImpl.java:548)

      at java.security.AccessController.doPrivileged(Native Method)

      at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:544)

      at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:479)

      at javafx.scene.control.Control.<clinit>(Control.java:81)

      ... 6 more

    bash$

  • 4. Re: headless LineChart?
    James_D Guru
    Currently Being Moderated

    I also tried a couple of experiments to see if I could get this to work, and couldn't find a way to do it. I was using Java 7.

     

    The closest I came was the following. It uses the Application class and the start(...) method, but without actually displaying anything on screen. I don't think this is truly "headless" though; since the FX Application thread is started up it probably needs the native windowing environment. And even this doesn't work; it produces the background of the chart but no data. I don't really know why this is, but my best guess is that the default stylesheet doesn't get applied as the scene is not rendered. (And that is a pure guess.)

     

    But I thought I'd share the code with you, just in case it's at all helpful. (Don't get your hopes up; it probably won't be.)

     

    import java.io.File;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.List;
    import javax.imageio.ImageIO;
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.embed.swing.SwingFXUtils;
    import javafx.scene.Scene;
    import javafx.scene.chart.CategoryAxis;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;
    import javafx.scene.image.Image;
    import javafx.stage.Stage;
    import javafx.util.StringConverter;
    public class HeadlessLineChart extends Application {
      @Override
      public void start(Stage primaryStage) {
        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis();
        yAxis.setTickLabelFormatter(new StringConverter<Number>() {
          @Override
          public Number fromString(String string) {
            return Double.parseDouble(string);
          }
          @Override
          public String toString(Number value) {
            return String.format("%2.2f", value);
          }
        });
        xAxis.setLabel("Month");
        final LineChart<String, Number> lineChart = new LineChart<String, Number>(
            xAxis, yAxis);
        lineChart.setTitle("Stock Monitoring, 2010");
        lineChart.setAnimated(false);
        final XYChart.Series<String, Number> series = new XYChart.Series<>();
        series.setName("My portfolio");
        final List<XYChart.Data<String, Number>> data = Arrays.asList(
        new XYChart.Data<String, Number>("Jan", 23),
            new XYChart.Data<String, Number>("Feb", 14),
            new XYChart.Data<String, Number>("Mar", 15),
            new XYChart.Data<String, Number>("Apr", 24),
            new XYChart.Data<String, Number>("May", 34),
            new XYChart.Data<String, Number>("Jun", 36),
            new XYChart.Data<String, Number>("Jul", 22),
            new XYChart.Data<String, Number>("Aug", 45),
            new XYChart.Data<String, Number>("Sep", 43),
            new XYChart.Data<String, Number>("Oct", 17),
            new XYChart.Data<String, Number>("Nov", 29),
            new XYChart.Data<String, Number>("Dec", 25));
        series.getData().addAll(data);
       
        Scene snapScene = new Scene(lineChart, 600, 400);
        Image image = snapScene.snapshot(null);
        try {
          ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", new File("chart.png"));
        } catch (Exception e) {
          e.printStackTrace();
        }
       
        Platform.exit();
      }
      public static void main(String[] args) throws IOException {
        launch(args);
      }
    }
  • 5. Re: headless LineChart?
    jsmith Guru
    Currently Being Moderated

    James, it is best to set animation off for the snapshot when taking a snapshot.

    Otherwise the chart snapshot could occur before the display animation has completed (effectively giving you just a background).

    It's not an issue with this line chart, but I have had to switch animation off for other charts like a pie chart.

     

    You also need to add the series data to the chart for the data to display ;-)

     

    lineChart.getData().addAll(series);
    lineChart.setAnimated(false);
    

     

    http://docs.oracle.com/javafx/2/api/javafx/scene/chart/Chart.html#setAnimated%28boolean%29

  • 6. Re: headless LineChart?
    jsmith Guru
    Currently Being Moderated

    There is an existing jira which indicates that the JavaFX team do have something which allows the system to be configured to run in headless mode:

     

    https://javafx-jira.kenai.com/browse/RT-20494  Headless Glass toolkit needs to be connected to Quantum and Prism unit tests

     

    The jira is likely just for an internal facility to allow the JavaFX team to run regression tests easier on a continuous integration server, so if you want something publicly supported it is best to file a feature request.

  • 7. Re: headless LineChart?
    James_D Guru
    Currently Being Moderated

    D'oh!

     

    I did have lineChart.setAnimated(false) buried in there. But yeah...

  • 8. Re: headless LineChart?
    KonradZuse Explorer
    Currently Being Moderated

    I'm still surprised they haven't finished the Headless Env yet...  I couldn't find anything on it when searching.

     

    The programming model http://www.oracle.com/us/technologies/java/javafx-2-prog-model-1524061.pdf page 6 states that it isn't done, but this is 2 years old so................

     

    I guess there isn't really much demand for it now...  I have a feeling I read something on OpenJDK that had something to do with Java 9 and Project Jigsaw.

  • 9. Re: headless LineChart?
    098a562b-359e-426b-b5e4-87df2c759fb4 Newbie
    Currently Being Moderated

    Thank you very much for your reply (and thanks to the others for their replies!). Also, thanks for the very useful link to the earlier post of processing charts in a second thread.

     

    We need to produce GUI charts as part of interactive use, but we also have an online system which is collecting data from radio telescopes. This online system also needs to produce charts. The hope was that we could find a library that would allow for both of these uses. I believe JFreeChart could do this, but JavaFX looks like it has the muscle of Oracle behind it... and it seems to produce nicer charts! I'll also use the link to post a feature request.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points