2016-09-28 14 views
8

JavaFXチャートAPIからチャート画像を生成したいだけです。私は、アプリケーションウィンドウを表示したり、アプリケーションを起動したりする必要はありません(必要でない場合)。 startメソッド内 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;} 
} 

は、私が実際に系列データを構築するために、外部のデータにアクセスする必要があるが、私はメンバ変数内のデータを保存する場合は、startメソッドから外部データにアクセスする方法があるようです data、開始時にnullになります。私は実際には、ステージやシーンのオブジェクトを気にしない限り、チャートの画像をレンダリングすることができます、どのように問題を解決する必要がありますか?私は、入力データで呼び出すことができ、データでグラフを描画し、そのファイルを返すAPIを構築したいと考えています。

public File toLineChart(List<Integer> data) { 
... 
} 
+0

私は何がやりたいことはFIRSTあると思う:ファイルからデータを読み込んで配列に格納するスキャナを使用しますか、その他のデータ型次へ:保存した情報をtoLineChartメソッドに渡す必要があります。 toLineChartメソッドは、以下のアイデアを使用してチャートを印刷する必要があります。データのオリジナルはどのように保存されているのですか?それはテキストファイルかデータベースですか? – Sedrick

答えて

6

あなたはStageを表示する必要はありませんが、NodeSceneに接続する必要があります。 doc of snapshotから:

注:CSSと正しく機能するレイアウトのために、ノードは (シーンがステージに取り付けることができるが、 がある必要はない)シーンの一部でなければなりません。 Sceneを変更する

一つの制限は、それがJavaFXのツールキットが初期化されなければならないという前提条件を持っているJ AVAFXアプリケーションスレッド、で発生しなければならないこと、です。

初期化がlaunch方法があなたのためにそれを行うだろうか、回避策として、あなたがスイングイベントディスパッチャスレッドに新しいJFXPanelインスタンスを作成することができApplicationクラスを拡張して行うことができます。

あなたがApplicationを拡張していて、start方法でいくつかのコードを実行した場合、そうでなければ、確実にするために別のスレッドから呼び出さPlatform.runLater(...)ブロックを使用することができ、このコードはのJavaFXアプリケーションスレッド上で実行されることが保証されます同じ。ここ

が可能な例である:

クラスがファイルにグラフをプロットするつの静的メソッドを提供し、作成が成功したかどうFile又はnullを返します。

は、この方法ではJavaFXのツールキットは、その後、チャートの作成がのJavaFXアプリケーションスレッドに行われスイングEDTJFXPanelを作成することによって初期化されます。この方法では、操作が完了し成功したことを格納するために2つのブール値が使用されます。

完了したフラグが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; 
    } 


} 

と考えられる使用コマンドラインから

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); 

と生成画像(charttest.png)

enter image description here

1

import java.io.File; 
import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.embed.swing.SwingFXUtils; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 
import javafx.scene.chart.*; 
import javafx.scene.Group; 
import javafx.scene.image.WritableImage; 
import javax.imageio.ImageIO; 

public class PieChartSample extends Application { 

    private static String[] arguments; 

    @Override public void start(Stage stage) { 
     Scene scene = new Scene(new Group()); 
     stage.setTitle("Imported Fruits"); 
     stage.setWidth(500); 
     stage.setHeight(500); 

     ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(); 

//    
     final PieChart chart = new PieChart(pieChartData); 
     chart.setTitle("Imported Fruits"); 
     for(int i = 0; i < arguments.length; i+=2) 
     { 
      System.out.println(arguments[i] + " " + arguments[i+1]); 
      chart.getData().add(new PieChart.Data(arguments[i], Double.parseDouble(arguments[i+1]))); 
     } 

     ((Group) scene.getRoot()).getChildren().add(chart); 

     saveAsPng(scene); 
     System.out.println("Done!"); 
     System.exit(0); 
     //stage.setScene(scene); 
     //stage.show(); 
    } 

    public static void main(String[] args) { 
     arguments = args; 
     launch(args); 
    } 

    static void saveAsPng(Scene scene){ 
     try 
     { 
      WritableImage image = scene.snapshot(null); 

      File file = new File("tempPieChart.png"); 

      ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file); 
     } 
     catch (IOException ex) 
     { 
      Logger.getLogger(PieChartSample.class.getName()).log(Level.SEVERE, null, ex); 
     } 

    } 
} 

次へ:プログラムをクリーンアップしてビルドします。その後 :あなたのdistフォルダにその後 をあなたのjarファイルを探す:あなたのjarファイルが入っているのdistフォルダにコマンドプロンプトをナビゲート 次に実行します。PieChartSample.jarバナナ-jar javaの14オレンジ20グレープ15

enter image description here

結果:あなたのPieChartSample.jarファイルと同じフォルダに

enter image description here

関連する問題