Obecnie używam itext-pdf do generowania plików PDF. Oprócz tego używam także JFreeChart do tworzenia wykresów na nim. Stworzyłem tabelę pączków z efektem eksplozji i wygląda to tak.Stwórz niestandardowy wykres pierścieniowy w JFreeChart
jednak Chcę utworzyć wykres pączka, który wygląda bardziej jak ten.
Chcę niektóre kawałki się wyróżniać, ale nie całkowicie się oderwane od wykres pierścieniowy. Byłbym bardzo wdzięczny za informacje, jak to osiągnąć.
Tu jest mój bieżący kod:
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());
}
}
}
Ta alternatywna wersja izoluje wykres z pliku PDF.
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);
}
}
@trashgod Czy wykres Szukam stworzyć nawet możliwe jfreecharts jeśli tak byłbym wdzięczny wejść – user1010101
ja nie zobacz dlaczego nie, ale być może będziesz musiał [podsumować] (http://stackoverflow.com/search?q=user%3A230513+%5Bjfreechart%5D+recapitulate) wiele z istniejącej implementacji; Dodałem alternatywną wersję na wypadek, gdyby ktoś chciał ją wypróbować. – trashgod
@trashgod dziękuję za izolowanie tego, ja również postawiłem nagrodę, więc jeśli sam lub ktokolwiek inny może dać mu szansę, byłoby świetnie, ponieważ nie mam pojęcia, od czego zacząć, nie jestem bardzo zaznajomiony z biblioteką jfreecharts, próbuję różnych hacki w międzyczasie, ale nic nie działa. – user1010101