2016-06-09 86 views
2

我想在JavaFX中創建一個圖表,將它放入一張圖片並將其放入PDF中,但在拍攝圖片之前我無法繪製圖形數據。顯然這張照片是在數據被繪製之前拍攝的。在這個例子中,我在框架頂部顯示圖片,在框架底部顯示圖片。如何同步Java和JavaFX線程?

什麼是同步Java和JavaFX的最佳方式?

enter image description here enter image description here

import java.awt.Dimension; 
    import java.io.ByteArrayOutputStream; 
    import java.io.IOException; 
    import java.util.Arrays; 
    import java.util.concurrent.CountDownLatch; 
    import java.util.logging.Level; 
    import java.util.logging.Logger; 
    import javafx.application.Platform; 
    import javafx.collections.FXCollections; 
    import javafx.embed.swing.JFXPanel; 
    import javafx.embed.swing.SwingFXUtils; 
    import javafx.geometry.Pos; 
    import javafx.scene.Scene; 
    import javafx.scene.SnapshotParameters; 
    import javafx.scene.chart.Axis; 
    import javafx.scene.chart.BarChart; 
    import javafx.scene.chart.CategoryAxis; 
    import javafx.scene.chart.NumberAxis; 
    import javafx.scene.chart.XYChart; 
    import javafx.scene.image.WritableImage; 
    import javafx.scene.layout.StackPane; 
    import javax.imageio.ImageIO; 

    public class JFXBarChart extends JFXPanel{ 
     private Scene scene; 
     private BarChart<String,Number> chart; 
     private String[] seriesColors; 
     private byte[] imageBytes = null; 

     public JFXBarChart(String[] xAxisCategories) { 
      Axis<String> xAxisCategory = new CategoryAxis(FXCollections.observableList(Arrays.asList(xAxisCategories))); 
      chart = new BarChart<>(xAxisCategory, new NumberAxis(0.0,10.0,1.0)); 
      chart.setPrefSize(300, 300); 
      setPreferredSize(new Dimension(300, 300)); 
      chart.setTitle("Chart"); 
      imageBytes = new byte[0]; 
      Platform.runLater(()->createScene()); 
     } 

     private void createScene(){ 
      StackPane stackPane = new StackPane(); 
      StackPane.setAlignment(chart, Pos.TOP_RIGHT); 
      stackPane.getChildren().addAll(chart); 
      scene = new Scene(stackPane); 
      setScene(scene); 
     }  

     public JFXBarChart setAllData(String serieName, final String[] x, final double[] y, CountDownLatch latch) { 
      if (y.length == x.length) { 
       Platform.runLater(() -> { 
        XYChart.Series<String, Number> currentSeries = new XYChart.Series<>(); 
        XYChart.Data<String, Number>[] data = new XYChart.Data[y.length]; 
        for (int i = 0; i < y.length; i++) { 
         XYChart.Data<String, Number> nodeData = new XYChart.Data<>(x[i], y[i]); 
         currentSeries.getData().add(nodeData); 
         data[i] = nodeData; 
        } 
        currentSeries.setName(serieName); 
        int newIndex = chart.getData().size(); 
        chart.getData().add(newIndex, currentSeries); 
        latch.countDown(); 
       }); 
      } 
      return this; 
     } 


     public byte[] getImageByteArray() { 
      return imageBytes; 
     } 

     public void convertChartToImageByteArray(CountDownLatch latch){ 
      Platform.runLater(() -> { 
       try { 
        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); 
        WritableImage wi = new WritableImage((int) chart.getPrefWidth(), (int) chart.getPrefHeight()); 
        chart.snapshot(new SnapshotParameters(), wi); 
        ImageIO.write(SwingFXUtils.fromFXImage(wi, null), "png", byteOutputStream); 
        byteOutputStream.flush(); 
        imageBytes = byteOutputStream.toByteArray(); 
        byteOutputStream.close(); 
       } catch (IOException ex) { 
        Logger.getLogger(JFXPanelBarChart.class.getName()).log(Level.SEVERE, null, ex); 
       }finally{ 
        latch.countDown(); 
       } 
      }); 
     } 
    } 




import com.itextpdf.io.image.ImageDataFactory; 
import com.itextpdf.kernel.geom.PageSize; 
import com.itextpdf.kernel.pdf.PdfDocument; 
import com.itextpdf.kernel.pdf.PdfWriter; 
import com.itextpdf.layout.Document; 
import com.itextpdf.layout.element.Image; 
import java.awt.BorderLayout; 
import java.io.ByteArrayInputStream; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.util.concurrent.CountDownLatch; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 

public class GeneratePDF { 

    private JFXBarChart chartLabel; 
    private JFXBarChart chartPDF; 

    public GeneratePDF() {} 

    public JLabel getLabel(){ 
     byte[] array = new byte[0]; 
     try { 
      array = createChart(chartLabel); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(GeneratePDF.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     java.awt.Image img = null; 
     try { 
      img = ImageIO.read(new ByteArrayInputStream(array)); 
     } catch (IOException ex) { 
      Logger.getLogger(GeneratePDF.class.getName()).log(Level.SEVERE, null, ex); 
     }   
     return new JLabel(new ImageIcon(img)); 
    } 

    public void createPdf(String path) throws FileNotFoundException{ 
     File file = new File(path); 
     OutputStream fos = new FileOutputStream(file); 
     PdfWriter writer = new PdfWriter(fos); 
     PdfDocument pdf = new PdfDocument(writer); 
     PageSize ps = new PageSize(612, 792); 
     Document document = new Document(pdf, ps); 
     byte[] array = new byte[0]; 
     try { 
      array = createChart(chartPDF); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(GeneratePDF.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     Image imgPDF = new Image(ImageDataFactory.create(array)); 
     document.add(imgPDF); 
     document.close(); 
    } 

    private byte[] createChart(JFXBarChart chart) throws InterruptedException { 
     CountDownLatch latch1 = new CountDownLatch(1); 
     chart = new JFXBarChart(new String[]{"a", "b"}) 
       .setAllData("Serie1", new String[]{"a", "b"}, new double[]{5.5, 6.5}, latch1); 
     latch1.await(); 
     CountDownLatch latch2 = new CountDownLatch(1); 
     chart.convertChartToImageByteArray(latch2); 
     latch2.await(); 
     byte[] array = chart.getImageByteArray(); 

     return array; 
    } 

    public JFXBarChart getPanelChart(){ 
     CountDownLatch latch = new CountDownLatch(1); 
     chartPDF = new JFXBarChart(new String[]{"a", "b"}) 
       .setAllData("Serie1", new String[]{"a", "b"}, new double[]{5.5, 6.5}, latch); 
     return chartPDF; 
    } 

    public static void main(String[] args) { 
     GeneratePDF pdfObject = new GeneratePDF(); 
     JFrame frame = new JFrame(); 
     frame.setSize(600, 600); 

     frame.getContentPane().add(pdfObject.getPanelChart(), BorderLayout.CENTER); 
     frame.getContentPane().add(pdfObject.getLabel(), BorderLayout.NORTH); 
     frame.setVisible(true); 
     try { 
      pdfObject.createPdf("E:\\Example.pdf"); 
     } catch (FileNotFoundException ex) { 
      Logger.getLogger(GeneratePDF.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
} 
+2

我沒有看你的代碼,但是你確定你的問題不僅僅是你有[動畫開啓你的圖表](http://stackoverflow.com/questions/14596688/javafx-i-want-to-save-chart-image-completely)? – jewelsea

回答

1

我會用這個職位的方法:(JavaFX thread synchronization with Java thread

new Thread() { 
    @Override 
    public void run() { 
     createPicture(); 
     Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
      updateChart(); 
      } 
     }); 
    } 
}.start();