2016-05-13 15 views
6

için özel bir zil tablosu hazırla PDF'ler oluşturmak için şu anda itext-pdf kullanıyorum. Buna ek olarak, üzerinde grafikler oluşturmak için JFreeChart kullanıyorum. Patlama etkisi olan bir çörek çizelgesi oluşturdum ve buna benziyor.JFreeChart

enter image description here

Ancak daha şöyle Halka grafik oluşturmak istiyorum.

enter image description here

Ben bazı bölümlerini öne istiyorum ama tamamen halka grafiğe ayrılmış alamadım. Bunu nasıl başaracağınıza dair girdileri çok takdir ediyorum.

import java.awt.Color; 
import java.awt.Graphics2D; 
import java.awt.geom.Rectangle2D; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.text.DecimalFormat; 
import java.util.Locale; 

import org.jfree.chart.ChartFactory; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.labels.StandardPieSectionLabelGenerator; 
import org.jfree.chart.plot.PiePlotState; 
import org.jfree.chart.plot.RingPlot; 
import org.jfree.data.general.DefaultPieDataset; 
import org.jfree.ui.RectangleInsets; 


import com.itextpdf.awt.DefaultFontMapper; 
import com.itextpdf.text.BaseColor; 
import com.itextpdf.text.Document; 
import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.Element; 
import com.itextpdf.text.Font; 
import com.itextpdf.text.PageSize; 
import com.itextpdf.text.Phrase; 
import com.itextpdf.text.pdf.BaseFont; 
import com.itextpdf.text.pdf.ColumnText; 
import com.itextpdf.text.pdf.PdfContentByte; 
import com.itextpdf.text.pdf.PdfTemplate; 
import com.itextpdf.text.pdf.PdfWriter; 

public class RingChartTest { 
    public static void main(String[] args) throws Exception { 
     new RingChartTest().createPDF(); 
    } 

    private void createPDF() throws Exception { 
     String destination = "ringchart.pdf"; 

     Document document = new Document(PageSize.A4.rotate()); 
     try { 
      PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(destination)); 
      document.open(); 

      // Create the pages 
      PdfContentByte cb = writer.getDirectContent(); 
      addChart(cb); 
     } catch (Exception e) { 
      System.out.println("Failure to generate the PDF"); 
      e.printStackTrace(); 
     } finally { 
      if (document != null) { 
       document.close();   
      } 
     } 
    } 

    private void addChart(PdfContentByte cb) throws Exception, IOException { 
     long pctPM = Math.round(20); 
     long pctOA = Math.round(15); 
     long pctWPI = Math.round(5); 
     long pctTDF = Math.round(25); 
     long pctNE = 100 - (pctPM + pctOA + pctWPI + pctTDF); 
     long pctEngaged = pctPM + pctOA + pctWPI; 
     long numEngaged = 3400; 
     String strNumEngaged = formatNumber(numEngaged, "#,###,###,##0"); 


     JFreeChart chart = createChart(pctPM, pctOA, pctWPI, pctTDF, pctNE); 

     int width = 300; 
     int height = 200; 
     PdfTemplate template = cb.createTemplate(width, height); 
     Graphics2D graphics2d = template.createGraphics(width, height, new DefaultFontMapper()); 
     Rectangle2D rectangle2d = new Rectangle2D.Double(0, 0, width, height); 
     chart.draw(graphics2d, rectangle2d); 
     graphics2d.dispose(); 
     cb.addTemplate(template, 30, 185); 

     // Add text inside chart 
     Font engagementFont = createFont("OpenSans-Bold.ttf", 8, 116, 112, 100); 
     Font percentFont1 = createFont("OpenSans-Light.ttf", 22, 116, 112, 100); 
     Font percentFont2 = createFont("OpenSans-Light.ttf", 10, 116, 112, 100); 
     Font numberFont = createFont("OpenSans-Regular.ttf", 8, 116, 112, 100); 
     addPhrase(cb, "ENGAGE", engagementFont, 135, 290, 230, 310, 10, Element.ALIGN_CENTER); 
     addPhrase(cb, String.valueOf(pctEngaged), percentFont1, 115, 270, 190, 289, 10, Element.ALIGN_RIGHT); 
     addPhrase(cb, "%", percentFont2, 191, 275, 201, 299, 10, Element.ALIGN_LEFT); 
     addPhrase(cb, "(" + strNumEngaged + ")", numberFont, 130, 258, 230, 278, 10, Element.ALIGN_CENTER); 

     // Create legend 
     // 290,420,370,520,10,Element.ALIGN_CENTER); 
     BaseFont engagedPctFont = createBaseFont("OpenSans-Bold.ttf"); 
     BaseFont engagedDescFont = createBaseFont("OpenSans-SemiBold.ttf"); 
     BaseFont nonEngagedDescFont = createBaseFont("OpenSans-Regular.ttf"); 
     BaseColor pmBaseColor = new BaseColor(31, 160, 200); 
     BaseColor oaBaseColor = new BaseColor(84, 193, 209); 
     BaseColor wpiBaseColor = new BaseColor(248, 156, 36); 
     BaseColor tdfBaseColor = new BaseColor(116, 112, 94); 
     BaseColor nonEngagedBaseColor = new BaseColor(148, 144, 132); 
     float x = 330; 
     float y = 350; 
     float radius = 3; 

     // Create border around legend 
     /* 
     cb.setColorFill(new BaseColor(255, 255, 255)); 
     cb.rectangle(320, 300, 150, 70); 
     cb.re 
     cb.fill(); 
     */ 
     BaseColor borderColor = new BaseColor(192, 189, 178); 
     cb.setColorStroke(borderColor); 
     cb.moveTo(320, 300); 
     cb.lineTo(320, 365); 
     cb.lineTo(500, 365); 
     cb.lineTo(500, 300); 
     cb.lineTo(320, 300); 
     cb.closePathStroke(); 

     // Prof Mgmt 
     cb.setColorFill(pmBaseColor); 
     cb.circle(x, y, radius); 
     cb.fill(); 
     addTextToCanvas(cb, pctPM+"%", engagedPctFont, 8, new BaseColor(116, 112, 100), x+20, y-2); 
     addTextToCanvas(cb, "Pg", engagedDescFont, 8, new BaseColor(116, 112, 100), x+50, y-2); 
     // Online Advice 
     cb.setColorFill(oaBaseColor); 
     cb.circle(x, y-20, radius); 
     cb.fill(); 
     addTextToCanvas(cb, pctOA+"%", engagedPctFont, 8, new BaseColor(116, 112, 100), x+20, y-22); 
     addTextToCanvas(cb, "Oaa", engagedDescFont, 8, new BaseColor(116, 112, 100), x+50, y-22); 
     // Clicked WPI/Online Guidance 
     cb.setColorFill(wpiBaseColor); 
     cb.circle(x, y-40, radius); 
     cb.fill(); 
     addTextToCanvas(cb, pctWPI+"%", engagedPctFont, 8, new BaseColor(116, 112, 100), x+20, y-42); 
     addTextToCanvas(cb, "Ogg", engagedDescFont, 8, new BaseColor(116, 112, 100), x+50, y-42); 
     if (pctTDF > 0) { 
      // TDF Users 
      cb.setColorFill(tdfBaseColor); 
      cb.circle(x, y-60, radius); 
      cb.fill(); 
      addTextToCanvas(cb, pctTDF+"%", engagedPctFont, 8, new BaseColor(116, 112, 100), x+20, y-62); 
      addTextToCanvas(cb, "Pti*", nonEngagedDescFont, 8, new BaseColor(116, 112, 100), x+50, y-62); 
      // Non-engaged 
      cb.setColorFill(nonEngagedBaseColor); 
      cb.circle(x, y-80, radius); 
      cb.fill(); 
      addTextToCanvas(cb, pctNE+"%", engagedPctFont, 8, new BaseColor(116, 112, 100), x+20, y-82); 
      addTextToCanvas(cb, "Nng", nonEngagedDescFont, 8, new BaseColor(116, 112, 100), x+50, y-82); 
     } else { 
      // Non-engaged 
      cb.setColorFill(nonEngagedBaseColor); 
      cb.circle(x, y-60, radius); 
      cb.fill(); 
      addTextToCanvas(cb, pctNE+"%", engagedPctFont, 8, new BaseColor(116, 112, 100), x+20, y-62); 
      addTextToCanvas(cb, "ngd", nonEngagedDescFont, 8, new BaseColor(116, 112, 100), x+50, y-62); 
     } 
    } 

    private String formatNumber(double value, String strFormat) { 
     DecimalFormat df = new DecimalFormat(strFormat); 
     return df.format(value); 
    } 

    private void addPhrase(PdfContentByte cb, String strText, Font font, float llx, float lly, float urx, float ury, float leading, int alignment) throws DocumentException { 
     Phrase phrase = new Phrase(strText, font); 
     ColumnText ct = new ColumnText(cb); 
     ct.setSimpleColumn(phrase, llx, lly, urx, ury, leading, alignment); 
     ct.go(); 
    } 

    private void addTextToCanvas(PdfContentByte cb, String strText, BaseFont font, float fontSize, BaseColor color, float x, float y) { 
     cb.beginText(); 
     cb.setFontAndSize(font, fontSize); 
     cb.setColorFill(color); 
     cb.showTextAligned(Element.ALIGN_LEFT, strText, x, y, 0); 
     cb.endText(); 
    } 

    private BaseFont createBaseFont(String fileName) throws DocumentException, IOException { 
     return BaseFont.createFont(PdfGenerationController.LOCATION_FONTS + fileName ,BaseFont.IDENTITY_H, BaseFont.EMBEDDED); 
    } 

    private Font createFont(String fileName, float size, int red, int green, int blue) throws DocumentException, IOException { 
     BaseFont baseFont = BaseFont.createFont(PdfGenerationController.LOCATION_FONTS + fileName ,BaseFont.IDENTITY_H, BaseFont.EMBEDDED); 
     Font font = new Font(baseFont, size); 
     font.setColor(red, green, blue); 
     return font; 
    } 

    public JFreeChart createChart(long pctPM, long pctOA, long pctWPI, long pctTDF, long pctNE) { 
     // Set up the data set for the donut/ring chart 
     DefaultPieDataset rDataSet = new DefaultPieDataset(); 
     rDataSet.setValue("PM", pctPM); 
     rDataSet.setValue("OA", pctOA); 
     rDataSet.setValue("WPI", pctWPI); 
     rDataSet.setValue("TDF", pctTDF); 
     rDataSet.setValue("NE", pctNE); 

     // Initialize values 
     boolean bShowLegend = false; 
     String strTitle = null; 

     // Create ring plot 
     CustomDonutPlot rPlot = new CustomDonutPlot(rDataSet); 
     //RingPlot rPlot = new RingPlot(rDataSet); 
     rPlot.setLabelGenerator(new StandardPieSectionLabelGenerator(Locale.ENGLISH)); 
     rPlot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); 
     rPlot.setSectionDepth(0.30); 
     JFreeChart chart = new JFreeChart(strTitle, JFreeChart.DEFAULT_TITLE_FONT, rPlot, bShowLegend); 
     ChartFactory.getChartTheme().apply(chart);   

     // Create the chart 
     //JFreeChart rChart = ChartFactory.createRingChart(null, rDataSet , false, false, Locale.ENGLISH); 
     //RingPlot rPlot = (RingPlot) rChart.getPlot(); 
     rPlot.setBackgroundPaint(Color.WHITE); 
     rPlot.setCenterText(null); 
     rPlot.setLabelGenerator(null); 
     rPlot.setOutlineVisible(false); 
     rPlot.setShadowGenerator(null); 
     rPlot.setSeparatorsVisible(false); 
     rPlot.setShadowPaint(null); 
     rPlot.setSectionOutlinesVisible(false); 
     rPlot.setOuterSeparatorExtension(0); 
     rPlot.setInnerSeparatorExtension(0); 

     // Set colors of the chart 
     rPlot.setSectionPaint("PM", new Color(31, 160, 200)); 
     rPlot.setSectionPaint("OA", new Color(84, 193, 209)); 
     rPlot.setSectionPaint("WPI", new Color(248, 156, 36)); 
     rPlot.setSectionPaint("TDF", new Color(116, 112, 94)); 
     rPlot.setSectionPaint("NE", new Color(148, 144, 132)); 

     rPlot.setExplodePercent("PM", 0.05); 
     rPlot.setExplodePercent("OA", 0.05); 
     rPlot.setExplodePercent("WPI", 0.05); 

     return chart; 
    } 

    public static class CustomDonutPlot extends RingPlot { 
     private static final long serialVersionUID = 1L; 

     public CustomDonutPlot(DefaultPieDataset dataSet) { 
      super(dataSet); 
     } 

     @Override 
     protected void drawItem(Graphics2D g2, int section, Rectangle2D dataArea, PiePlotState state, int currentPass) { 
      if (currentPass == 1 && section >=1 && section <= 3) { 

      } 
      Rectangle2D area = state.getPieArea(); 
      System.out.println("*** At section=" + section + ", pass="+currentPass); 
      logDataArea(dataArea, "Data area"); 
      logDataArea(area, "Pie area"); 
      System.out.println(state.getInfo()); 

      super.drawItem(g2, section, dataArea, state, currentPass); 


     } 

     private void logDataArea(Rectangle2D dataArea, String msg) { 
      System.out.println(msg + " h="+dataArea.getHeight() + ", w=" + dataArea.getWidth() + ", x=" + dataArea.getX() + ",y="+dataArea.getY()); 
     } 


    } 
} 

Bu alternatif sürümü PDF grafiği izole:

İşte benim şimdiki kodudur.

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics2D; 
import java.awt.geom.Rectangle2D; 
import java.util.Locale; 
import javax.swing.JFrame; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.labels.StandardPieSectionLabelGenerator; 
import org.jfree.chart.plot.PiePlotState; 
import org.jfree.chart.plot.RingPlot; 
import org.jfree.data.general.DefaultPieDataset; 
import org.jfree.ui.RectangleInsets; 

/** 
* @see http://stackoverflow.com/q/37213030/230513 
*/ 
public class Test { 

    private void display() { 
     JFrame f = new JFrame("Test"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     long pctPM = Math.round(20); 
     long pctOA = Math.round(15); 
     long pctWPI = Math.round(5); 
     long pctTDF = Math.round(25); 
     long pctNE = 100 - (pctPM + pctOA + pctWPI + pctTDF); 
     f.add(new ChartPanel(createChart(pctPM, pctOA, pctWPI, pctTDF, pctNE))); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public JFreeChart createChart(long pctPM, long pctOA, long pctWPI, long pctTDF, long pctNE) { 
     // Set up the data set for the donut/ring chart 
     DefaultPieDataset rDataSet = new DefaultPieDataset(); 
     rDataSet.setValue("PM", pctPM); 
     rDataSet.setValue("OA", pctOA); 
     rDataSet.setValue("WPI", pctWPI); 
     rDataSet.setValue("TDF", pctTDF); 
     rDataSet.setValue("NE", pctNE); 

     // Initialize values 
     boolean bShowLegend = false; 
     String strTitle = null; 

     // Create ring plot 
     CustomDonutPlot rPlot = new CustomDonutPlot(rDataSet); 
     //RingPlot rPlot = new RingPlot(rDataSet); 
     rPlot.setLabelGenerator(new StandardPieSectionLabelGenerator(Locale.ENGLISH)); 
     rPlot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0)); 
     rPlot.setSectionDepth(0.30); 
     JFreeChart chart = new JFreeChart(strTitle, JFreeChart.DEFAULT_TITLE_FONT, rPlot, bShowLegend); 
     ChartFactory.getChartTheme().apply(chart); 

     // Create the chart 
     //JFreeChart rChart = ChartFactory.createRingChart(null, rDataSet , false, false, Locale.ENGLISH); 
     //RingPlot rPlot = (RingPlot) rChart.getPlot(); 
     rPlot.setBackgroundPaint(Color.WHITE); 
     rPlot.setCenterText(null); 
     rPlot.setLabelGenerator(null); 
     rPlot.setOutlineVisible(false); 
     rPlot.setShadowGenerator(null); 
     rPlot.setSeparatorsVisible(false); 
     rPlot.setShadowPaint(null); 
     rPlot.setSectionOutlinesVisible(false); 
     rPlot.setOuterSeparatorExtension(0); 
     rPlot.setInnerSeparatorExtension(0); 

     // Set colors of the chart 
     rPlot.setSectionPaint("PM", new Color(31, 160, 200)); 
     rPlot.setSectionPaint("OA", new Color(84, 193, 209)); 
     rPlot.setSectionPaint("WPI", new Color(248, 156, 36)); 
     rPlot.setSectionPaint("TDF", new Color(116, 112, 94)); 
     rPlot.setSectionPaint("NE", new Color(148, 144, 132)); 

     rPlot.setExplodePercent("PM", 0.05); 
     rPlot.setExplodePercent("OA", 0.05); 
     rPlot.setExplodePercent("WPI", 0.05); 

     return chart; 
    } 

    public static class CustomDonutPlot extends RingPlot { 

     private static final long serialVersionUID = 1L; 

     public CustomDonutPlot(DefaultPieDataset dataSet) { 
      super(dataSet); 
     } 

     @Override 
     protected void drawItem(Graphics2D g2, int section, Rectangle2D dataArea, PiePlotState state, int currentPass) { 
      super.drawItem(g2, section, dataArea, state, currentPass); 
      Rectangle2D area = state.getPieArea(); 
      System.out.println("*** At section=" + section + ", pass=" + currentPass); 
      logDataArea(dataArea, "Data area"); 
      logDataArea(area, "Pie area"); 
     } 

     private void logDataArea(Rectangle2D dataArea, String msg) { 
      System.out.println(msg + " h=" + dataArea.getHeight() + ", w=" + dataArea.getWidth() + ", x=" + dataArea.getX() + ",y=" + dataArea.getY()); 
     } 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Test()::display); 
    } 
} 
+0

@trashgod yüzden ben benim yok – user1010101

+0

girişler seviniriz eğer jfreecharts ile bile mümkün oluşturmak için arıyorum grafik mı: kodunuzu (iç sınıfı) aşağıda görüntü elde etmek güncelleyin neden olmasın diye bakın, ancak mevcut uygulamaların çoğunu [recapitulate] (http://stackoverflow.com/search?q=user%3A230513+%5Bjfreechart%5D+recapitulate) yapmanız gerekebilir; Birisi onu vermek istediğinde alternatif versiyonu ekledim. – trashgod

+0

@trashgod bunu ayırdığın için teşekkürler, ben de kendimi ya da başkası bir gitmek verebilir bu yüzden ben de ödünç koydum böylece nerede ben jfreecharts kütüphanesi ile çok aşina değilim başlamak için hiçbir fikrim yok gibi büyük olurdu, ben çeşitli çalışıyorum Bu arada hack ama hiçbir şey çalışmıyor. – user1010101

cevap

4

Patlatılmış yayınızı patlamamış olan tarafa çekmeniz gerektiği gibi görünüyor. Bunu yapmak için RingPlot::getArcBounds'u geçersiz kılabilir ve ark sınırlarıyla çalışabilirsiniz.

image

public static class CustomDonutPlot extends RingPlot { 
    private static final long serialVersionUID = 1L; 

    public CustomDonutPlot(DefaultPieDataset dataSet) { 
     super(dataSet); 
    } 

    @Override 
    protected void drawItem(Graphics2D g2, int section, Rectangle2D dataArea, PiePlotState state, int currentPass) { 
     if (currentPass == 1 && section >=1 && section <= 3) { 

     } 
     Rectangle2D area = state.getPieArea(); 
     System.out.println("*** At section=" + section + ", pass="+currentPass); 
     logDataArea(dataArea, "Data area"); 
     logDataArea(area, "Pie area"); 
     System.out.println(state.getInfo()); 

     super.drawItem(g2, section, dataArea, state, currentPass); 


    } 
    @Override 
    protected Rectangle2D getArcBounds(Rectangle2D unexploded, Rectangle2D exploded, double angle, double extent, double explodePercent) { 
     if(explodePercent > 0.0){ 
      this.setSectionDepth(0.33);//to match inner arc 
      java.awt.geom.Arc2D.Double arc1 = new java.awt.geom.Arc2D.Double(unexploded, angle, extent/2.0D, 0); 
      Point2D point1 = arc1.getEndPoint(); 
      //java.awt.geom.Arc2D.Double arc2 = new java.awt.geom.Arc2D.Double(exploded, angle, extent/2.0D, 0); //original code 
      Rectangle2D mix = new Rectangle2D.Double(exploded.getX(), exploded.getY(), unexploded.getWidth(), unexploded.getHeight()); 
      java.awt.geom.Arc2D.Double arc2 = new java.awt.geom.Arc2D.Double(mix, angle, extent/2.0D, 0); 

      Point2D point2 = arc2.getEndPoint(); 
      double deltaX = (point1.getX() - point2.getX()) * explodePercent; 
      double deltaY = (point1.getY() - point2.getY()) * explodePercent; 
      //return new java.awt.geom.Rectangle2D.Double(unexploded.getX() - deltaX, unexploded.getY() - deltaY, unexploded.getWidth(), unexploded.getHeight()); original code 
      return new java.awt.geom.Rectangle2D.Double(unexploded.getX() - deltaX, unexploded.getY() - deltaY, exploded.getWidth(), exploded.getHeight()); 
     } else { 
      this.setSectionDepth(0.3);//default depth 
      return super.getArcBounds(unexploded, exploded, angle, extent, explodePercent); 
     } 
    } 


    private void logDataArea(Rectangle2D dataArea, String msg) { 
     System.out.println(msg + " h="+dataArea.getHeight() + ", w=" + dataArea.getWidth() + ", x=" + dataArea.getX() + ",y="+dataArea.getY()); 
    } 


} 
+0

Patlatılmış bölümün iç arkına ihtiyacınız varsa, diğer bölümlerin aynı dairesinde olacaksanız, bölümün derinliğini this.setSectionDepth (0.33) ile hesaplamanız ve ayarlamanız gerekecektir. – fhofmann

+0

Bu, şu andaki çekme yöntemini geçersiz kılmamın yerine geçeceğimi ümit ediyor gibi görünüyor. Mümkünse çözümünüzü cevabım ile bağlam içinde gönderirseniz, ben de deneyebilirim ve cevabınızı kabul edebilir miyim? – user1010101

+0

Ben senin yaklaşımını deniyorum bazı hata alıyorum, belki yanlış bir şey yapıyorum. Kodumda tam olarak nereye gittiğimi açıklığa kavuşturur musun lütfen. – user1010101