how can I embed 2 bars chart in html using java? - java

I generate html page with java using gagawa
I now try to add a charts like this:
I have tried org.jfree framework
with this code:
private Img createChart(LatencyHistogram current, LatencyHistogram baseLine) {
Img image = null;
final CategoryDataset dataset = createDataset(current, baseLine);
final JFreeChart chart = ChartFactory.createLineChart(
"Line Chart Demo 1", // chart title
"Type", // domain axis label
"Value", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(java.awt.Color.white);
// save it to an image
try {
final ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
final String pathname = Constants.HTML_PAGES_PATH + "images/latency_delta.png";
final File file1 = new File(pathname);
ChartUtilities.saveChartAsPNG(file1, chart, 600, 400, info);
image = new Img("latency", "../images/latency_delta.png").setWidth("400");
return image;
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
and got this result:
is there any way to create 2 bars chart instead?
is there a more clean and tidy free java charts drawer framework?

to create a bar chart you should use
ChartFactory.createBarChart()
instead of
ChartFactory.createLineChart()
method .but since i don't know what is LatencyHistogram in your code this is not exact code.you have to currently use those data types .
for example following code will generate this
example code
import java.awt.Color;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class BarChartx extends ApplicationFrame {
public BarChartx(String applicationTitle, String chartTitle) {
super(applicationTitle);
JFreeChart barChart = ChartFactory.createBarChart(chartTitle, "year", "value", createDataset(), PlotOrientation.VERTICAL, true, true, false);
CategoryPlot p = barChart.getCategoryPlot();
BarRenderer renderer = (BarRenderer) p.getRenderer();
renderer.setSeriesPaint(0, new Color(255, 0, 102));
renderer.setSeriesPaint(1, new Color(0, 153, 255));
renderer.setItemMargin(0.03);
ChartPanel chartPanel = new ChartPanel(barChart);
chartPanel.setPreferredSize(new java.awt.Dimension(560, 367));
setContentPane(chartPanel);
}
private CategoryDataset createDataset() {
final String apple = "apple";
final String mango = "mango";
final String y2000 = "2000";
final String y2001 = "2001";
final String y2002 = "2002";
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(700, apple, y2000);
dataset.addValue(550, mango, y2000);
dataset.addValue(700, apple, y2001);
dataset.addValue(550, mango, y2001);
dataset.addValue(720, apple, y2002);
dataset.addValue(570, mango, y2002);
return dataset;
}
public static void main(String[] args) {
BarChartx chart = new BarChartx("example", "Bar Chart Demo 1");
chart.pack();
RefineryUtilities.centerFrameOnScreen(chart);
chart.setVisible(true);
}
}

Related

Semi donut chart in jfreechart

How to draw a semi do nut chart in jfreechart , For example use this below link, https://www.highcharts.com/demo/pie-semi-circle
This is my code
DefaultPieDataset dataset = new DefaultPieDataset( );
dataset.setValue("Safari-32", new Long( 32) ); dataset.setValue("Chrome-44", new Long( 44) );
dataset.setValue("Apple-24", new Long( 24) );
dataset.setValue("Google-75", new Long( 75) );
dataset.setValue("Michele", new Long( 97) ); dataset.setValue("Jony", new Long( 41) );
JFreeChart chart = ChartFactory.createRingChart("Chart title", dataset, true, false, false);
chart.setBackgroundPaint(Color.WHITE);
chart.setBorderVisible(false);
RingPlot plots = (RingPlot) chart.getPlot();
Font font3 = new Font("Book Antiqua", Font.BOLD, 17);
plots.setShadowPaint(null);
plots.setBackgroundPaint(null);
plots.setOutlineVisible(false);
plots.setLabelOutlinePaint(null);
plots.setLabelBackgroundPaint(Color.WHITE);
plots.setCenterTextMode(CenterTextMode.FIXED);
String te = "334";
plots.setCenterText((String)te); plots.setCenterTextFont(font3);
plots.setLabelGenerator(null); // Remove the labels from chart area
font3 = new Font("Book Antiqua", Font.PLAIN, 10);
LegendTitle legend = chart.getLegend();
legend.setPosition(RectangleEdge.RIGHT); legend.setItemFont(font3);
legend.setBorder(0, 0, 0, 0);
String filename = "D:\\ad\\do nut.jpg";
ChartUtilities.saveChartAsJPEG(new File(filename), chart, 250, 155);
This is my code and this produces a full donut chart. I need a donut of starting angle from 180 degree to 0 degree
Initial
Refresh
It's quite simple to create a semi/half donut in java using jfreechart. The most important thing is the invisible dataset. My favourite aircraft is the F16 Falcon, but my code below doesn't have any military associations. Feel free to reuse and/or adapt the source code.
Description: Example class to demonstrate semi/half-donut (TAGS: java, osgi, jfreechart, version 1.0.19, SWT, #PostConstruct, ChartComposite, Eclipse, E4, PiePlot, RingPlot, Semi, Half, Example, BackgroundImage, Resizing, Layout)
package de.enjo.jfreechart.semi.donut.example.parts;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Objects;
import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.e4.ui.di.UISynchronize;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.RingPlot;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.experimental.chart.swt.ChartComposite;
/*
* Example class to demonstrate semi/half-donut with jfreechart version 1.0.19
* (SWT, ChartComposite, Eclipse, E4, jfreechart, PiePlot, RingPlot, Semi, Half, Example)
*
* #note: This example doesn't use the ChartPanel class to avoid an additional Swing-UI Thread
* */
public class SamplePart {
// synchronize ui, i.e. dataset has been changed
#Inject
private UISynchronize uiSync;
// refresh ui job
private final Job refreshJob = new Job("Refresh Job") {
#Override
protected IStatus run(IProgressMonitor monitor) {
uiSync.asyncExec(SamplePart.this::updateUI);
return Status.OK_STATUS;
}
};
// invisible dataset, the most important thing
private final String INVISIBLE = "have_a_look_on_me_if_you_can_xD";
// an awt image
private BufferedImage backgroundImage;
// color white
private org.eclipse.swt.graphics.Color backgroundColor = new org.eclipse.swt.graphics.Color(255, 255, 255);
private java.awt.Color whiteColorAlphaChannel = new java.awt.Color(255, 255, 255, 0);
// swt widget
private ChartComposite chartComposite;
// the colors we need/support
private ColorRegistry colors;
public SamplePart() {
colors = new ColorRegistry();
colors.put("COLOR" + 0, new RGB(0, 0, 255));
colors.put("COLOR" + 1, new RGB(0, 255, 0));
colors.put("COLOR" + 2, new RGB(255, 0, 0));
colors.put("COLOR" + 3, new RGB(0, 255, 255));
colors.put("COLOR" + 4, new RGB(255, 255, 0));
colors.put("COLOR" + 5, new RGB(128, 128, 128));
}
/**
* initializing ui & simulate data change via refresh job (delay 3 seconds)
*
* #note: wait 3 seconds after starting to refresh
*/
#PostConstruct
public void createComposite(Composite parent) {
initializeExample(parent);
refreshJob.schedule(3000);// milliseconds
}
// construct and set all defaults
private void initializeExample(Composite parent) {
parent.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).create());
parent.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
parent.setBackground(backgroundColor); // white
/**
* 1st load background image
*/
try {
// no really military associations
backgroundImage = loadImage();
} catch (Exception e) {
/* ignore , it has to be present */}
/**
* 2nd create composite (swt)
*/
chartComposite = new ChartComposite(parent, SWT.NONE);
chartComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
chartComposite.setDomainZoomable(false);// no zoom needed
chartComposite.setRangeZoomable(false);// no zoom needed
/**
* 3rd create dataset (important thing (...most important thing...*fg))
*
* - don't forget to decrease by the previous value (degree of previous value =>
* array[index-1])
*
* - you need an additional, invisible dataset to complete the pie or ring plot
* up to 100% (360° or 1.0f)
*
* FYI: 0.0f-1.0f <> 0%-100% <> 0°-360°
*/
DefaultPieDataset dataset = new DefaultPieDataset();
// in this example we use a range of 0°-180°
int[] degreeValues = new int[] { 45, 90, 135, 180 };// 45°, 90° etc.
for (int index = 0; index < degreeValues.length; index++) {
if (index == 0) {
dataset.setValue(String.valueOf(index), Math.toRadians(degreeValues[index]));
} else {
dataset.setValue(String.valueOf(index), Math.toRadians(degreeValues[index] - degreeValues[index - 1]));
}
}
// MOST IMPORTANT
// invisible dataset to complete pie chart up to 100%
// you can use any other numbered key here, in my case the key is named:
// have_a_look_on_me_if_you_can_xD (should be unique)
dataset.setValue(INVISIBLE, Math.toRadians(180));// semi => 180°, we have 360° now
/**
* 4th create plot & chart
*/
final RingPlot plot = new RingPlot(dataset);
plot.setOutlineVisible(false);
plot.setLabelGenerator(null);
for (int index = 0; index < degreeValues.length; index++) {
plot.setSectionPaint(String.valueOf((index)), getAWTColor(index));
// section stroke line for better visibility
plot.setSectionOutlinePaint(String.valueOf((index)), new java.awt.Color(213, 54, 0));
}
// MOST IMPORTANT
// invisible section to complete pie chart up to 100%
// you can use any other numbered key here, in my case the key is named:
// have_a_look_on_me_if_you_can_xD (should be unique)
plot.setSectionPaint(INVISIBLE, whiteColorAlphaChannel); // 180° alpha invisible
plot.setSectionOutlinePaint(INVISIBLE, whiteColorAlphaChannel); // 180° alpha invisible
//
plot.setBackgroundImage(backgroundImage);// you can also use a picture of your grandma ^^
plot.setBackgroundImageAlpha(1.0f); // background image without transparent channel
plot.setForegroundAlpha(0.5f); // plots drawing with transparent channel (semi)
plot.setSectionDepth(0.9D);// ring depth/width in double
plot.setCircular(true); // no ellipse
plot.setInnerSeparatorExtension(0.2f);// percent of inner separator strokes
plot.setOuterSeparatorExtension(0.2f);// percent of outer separator strokes
plot.setSectionOutlinesVisible(true);// strokes between datasets
plot.setSeparatorPaint(new java.awt.Color(213, 54, 0)); // stroke paint
plot.setShadowPaint(null);// no shadow drawing needed (i'm always on the bright side of life... :P)
/**
* #note: edit image to correct size and position of AOI (area-of-interest)
* first before use these settings
*
* #note: setBackgroundImageAlignment(0) = resize of image is disabled. Comment
* it out to enable auto resizing (not recommended in this case)
*/
plot.setInteriorGap(0.0D);
plot.setBackgroundImageAlignment(0);
//
final JFreeChart chart = new JFreeChart(null, null, plot, false);
chart.setBackgroundPaint(new java.awt.Color(parent.getBackground().getRed(), parent.getBackground().getGreen(),
parent.getBackground().getBlue()));
/*
* 5th complete initialization
*/
chartComposite.setChart(chart);
}
private java.awt.Color getAWTColor(int index) {
/*
* ensure that dataset size/length does not exceed the color size/length
*/
org.eclipse.swt.graphics.Color color = colors.get("COLOR" + index);
return new java.awt.Color(color.getRed(), color.getGreen(), color.getBlue());
}
// is called by the refresh job
public void updateUI() {
// simulate date change
if (Objects.nonNull(chartComposite) && !chartComposite.isDisposed()) {
chartComposite.setRedraw(false);
DefaultPieDataset dataset = new DefaultPieDataset();
// in this example we use a range 0°-180°, 6 colors are supported
int[] degreeValues = new int[] { 30, 60, 90, 120, 150, 180 };// 30°, 60° etc.
for (int index = 0; index < degreeValues.length; index++) {
if (index == 0) {
dataset.setValue(String.valueOf(index), Math.toRadians(degreeValues[index]));
} else {
dataset.setValue(String.valueOf(index),
Math.toRadians(degreeValues[index] - degreeValues[index - 1]));
}
}
// MOST IMPORTANT
// invisible dataset to complete pie chart up to 100%
// you can use any other numbered key here, in my case the key is named:
// have_a_look_on_me_if_you_can_xD (should be unique)
dataset.setValue(INVISIBLE, Math.toRadians(180));// semi => 180°, we have 360° now
((RingPlot) chartComposite.getChart().getPlot()).setDataset(dataset);
chartComposite.setRedraw(true);
}
}
/*
* ############################# helper area ############################
*/
private BufferedImage loadImage() throws Exception {
/**
* #note: image source:
* https://www.pngarea.com/view/e6f205a3_jet-png-f-16-plane-png-transparent-png/
*
* #note: put this image into the icons directory, named "f16.png" and replace
* transparent background with white background color first
*
* #note: this example has no military associations. I like this aircraft, not
* more :). You can use every other image with white background in this
* example
*/
return getBufferedImage(SamplePart.class.getResourceAsStream("/icons/f16.png"));
}
private BufferedImage getBufferedImage(InputStream inputStream) throws Exception {
byte[] bytes = read(inputStream);
return getBufferedImage(bytes);
}
/*
* load resources without additional plugins, like emf etc.
*/
private byte[] read(InputStream is) throws Exception {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead = 0;
byte[] data = new byte[is.available()];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] bytes = buffer.toByteArray();
buffer.close();
is.close();
return bytes;
}
private BufferedImage getBufferedImage(byte[] bytes) throws Exception {
InputStream is = new ByteArrayInputStream(bytes);
BufferedImage bufferedImage = ImageIO.read(is);
is.close();
return bufferedImage;
}
}
I need a donut of starting angle from 180 degree to 0 degree.
You can start at 180° using the parent PiePlot method setStartAngle(). You can hide the lower half using a transparent color, as shown here, or cover it using one of the approaches shown here. OverlayLayout and transparent white is illustrated below.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.RingPlot;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
public class RingChartTest {
private PieDataset createDataset() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("Safari", 75);
dataset.setValue("Chrome", 60);
dataset.setValue("FireFox", 45);
dataset.setValue("", 180);
return dataset;
}
private JFreeChart createChart(PieDataset dataset) {
JFreeChart chart = ChartFactory.createRingChart(
"Browser Share", dataset, true, false, false);
RingPlot plot = (RingPlot) chart.getPlot();
plot.setStartAngle(180);
plot.setCircular(true);
plot.setSimpleLabels(true);
plot.setSectionDepth(0.5);
plot.setBackgroundPaint(Color.WHITE);
Color invisible = new Color(0xffffffff, true);
plot.setSectionPaint("", invisible);
plot.setSectionOutlinePaint("", invisible);
plot.setShadowPaint(null);
//plot.setLabelGenerator(null);
return chart;
}
public JPanel createDemoPanel() {
JFreeChart jfreechart = createChart(createDataset());
ChartPanel chartPanel = new ChartPanel(jfreechart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 400);
}
};
chartPanel.setLayout(new OverlayLayout(chartPanel));
JLabel label = new JLabel("BrowserShare");
label.setFont(label.getFont().deriveFont(48.0f));
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
label.setAlignmentX(0.5f);
label.setAlignmentY(0.75f);
label.setOpaque(true);
label.setBackground(Color.LIGHT_GRAY);
chartPanel.add(label);
return chartPanel;
}
public static void main(String args[]) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame("Ring Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new RingChartTest().createDemoPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}

JFreeChart StackedXYAreaRenderer causes "crimp" in chart

I'm using JFreeChart to show a stacked line chart of two sets of data over time, in this example dogs and cats.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYAreaRenderer;
import org.jfree.data.time.Minute;
import org.jfree.data.time.TimeTableXYDataset;
public class ChartTest {
public ChartTest() throws ParseException{
TimeTableXYDataset chartData = createChartData();
JFreeChart chart = createChart(chartData);
ChartPanel chartPanel = new ChartPanel(chart);
JFrame frame = new JFrame("Chart Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(chartPanel);
frame.setSize(500, 500);
frame.setVisible(true);
}
private TimeTableXYDataset createChartData() throws ParseException {
int[] dogs = {14, 81, 99, 89, 151, 263, 396, 548, 822, 1410, 2180, 3134, 4065, 5016, 6019, 7648, 9323, 11059, 12252, 13432, 15238, 17559, 19796, 21853, 23971, 26414, 28694, 31371, 34233, 37353, 40451, 44081, 47978, 52040, 56024, 60486, 64881, 69663, 74320, 79391, 84840, 91228, 96383, 102061, 107832, 114244, 119992, 126207, 132894, 139146, 144727, 150896, 156503, 161960, 167724, 174172, 180121, 185929, 191375, 196050, 200768, 205208, 208727, 212329, 216439, 221102, 224284, 226944, 230307, 233075, 234814, 236220, 237733, 239158, 240311, 241267};
int[] cats = {244, 360, 363, 644, 1075, 1516, 2241, 3160, 3591, 4661, 5633, 6990, 7889, 9059, 10510, 11743, 12506, 13540, 14557, 15705, 16969, 18350, 20197, 21659, 23160, 24840, 26394, 28109, 29742, 31428, 33021, 34514, 35822, 37339, 38784, 40258, 41568, 42921, 44180, 45454, 46710, 48084, 49418, 50712, 51920, 53014, 53923, 54830, 55756, 56573, 57554, 58352, 59064, 59874, 60933, 61948, 62762, 63299, 63772, 64243, 64789, 65206, 65693, 66016, 66391, 66859, 67432, 67919, 68400, 68677, 68944, 69211, 69511, 69786, 69990, 70279};
final TimeTableXYDataset chartData = new TimeTableXYDataset();
long start = new SimpleDateFormat("MM/dd/yyyy HH:mm").parse("11/08/2016 08:00").getTime();
for (int t = 0; t < dogs.length; t++) {
Minute m = new Minute(new Date(start + 15*t*60*1000));
chartData.add(m, dogs[t], "Dogs");
chartData.add(m, cats[t], "Cats");
}
return chartData;
}
private JFreeChart createChart(TimeTableXYDataset chartData) {
JFreeChart chart = ChartFactory.createStackedXYAreaChart("Dogs and Cats", "Time", "Count", chartData, PlotOrientation.VERTICAL, false, true, false);
StackedXYAreaRenderer chartRenderer = new StackedXYAreaRenderer();
XYPlot plot = (XYPlot)chart.getPlot();
plot.setRenderer(chartRenderer);
DateAxis dateAxis = new DateAxis();
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
plot.setDomainAxis(dateAxis);
return chart;
}
public static void main(String... args) throws ParseException{
new ChartTest();
}
}
However, this results in a "crimp" in the cats section of the chart:
I've looked my data over, and it doesn't contain negative values or anything strange that might throw the chart off.
Through some shotgun debugging, I realized that if I remove this section of code from the createChart() function:
StackedXYAreaRenderer chartRenderer = new StackedXYAreaRenderer();
XYPlot plot = (XYPlot)chart.getPlot();
plot.setRenderer(chartRenderer);
DateAxis dateAxis = new DateAxis();
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
plot.setDomainAxis(dateAxis);
Then I get a more reasonable stacked line chart:
But then I lose my nicely formatted dates.
My questions are:
What is causing the "crimp" in the cats section of the chart, and the space between the two stacks?
Is there a different way to format the dates that doesn't cause this behavior?
ChartFactory.createStackedXYAreaChart() instantiates StackedXYAreaRenderer2 to avoid this problem. Your example replaces it with an instance of StackedXYAreaRenderer. Either,
Use the factory's renderer and a custom DateAxis.
private JFreeChart createChart(TimeTableXYDataset chartData) {
JFreeChart chart = ChartFactory.createStackedXYAreaChart(
"Dogs and Cats", "Time", "Count", chartData,
PlotOrientation.VERTICAL, false, true, false);
DateAxis dateAxis = new DateAxis();
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDomainAxis(dateAxis);
return chart;
}
Recapitulate the factory, as shown here, in your createChart() method.
private JFreeChart createChart(TimeTableXYDataset chartData) {
DateAxis dateAxis = new DateAxis("Time");
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
NumberAxis yAxis = new NumberAxis("Count");
XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
StackedXYAreaRenderer2 renderer = new StackedXYAreaRenderer2(
toolTipGenerator, null);
renderer.setOutline(true);
XYPlot plot = new XYPlot(chartData, dateAxis, yAxis, renderer);
plot.setOrientation(PlotOrientation.VERTICAL);
plot.setRangeAxis(yAxis); // forces recalculation of the axis range
JFreeChart chart = new JFreeChart("Dogs and Cats",
JFreeChart.DEFAULT_TITLE_FONT, plot, false);
new StandardChartTheme("JFree").apply(chart);
return chart;
}
Can you expand a little bit on why the StackedXYRenderer causes that crimp?
The author writes, "StackedXYAreaRenderer2 uses a different drawing approach, calculating a polygon for each data point and filling that." In contrast, StackedXYAreaRenderer appears to close a single Shape by connecting the endpoints with a straight line.

Adding values to JFreeChart XYDataset from csv file using opencsv

I am trying to read in a .csv file but I am stuck on how once I've read each line on the csv file and how to add it to the XYDataset.
My algorithm is as follows: read in .csv file -> read each line -> add to dataset -> create chart -> output as frame
data.csv has 4 columns: Time, X, Y, Z
How do I add each point (time,x), (time,y), (time,z) to the dataset?
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import com.opencsv.CSVReader;
public class Test extends ApplicationFrame
{
XYDataset dataset;
JFreeChart chart;
final ChartPanel chartPanel;
final int chartWidth = 560;
final int chartHeight = 367;
CSVReader reader;
String[] readNextLine;
XYSeries series;
public Test(String applicationTitle) throws IOException
{
super(applicationTitle);
dataset = createDataset();
chart = createChart(dataset);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(chartHeight, chartWidth));
}
public XYDataset createDataset() throws NumberFormatException, IOException
{
dataset = new XYSeriesCollection();
try
{
reader = new CSVReader(new FileReader("data.csv"));
while((readNextLine = reader.readNext()) != null)
{
if (readNextLine != null)
{
//add values to dataset
}
}
}
catch (FileNotFoundException e)
{
System.out.println("File not found!");
}
return dataset;
}
public JFreeChart createChart(XYDataset dataset) throws NumberFormatException, IOException
{
chart = ChartFactory.createXYLineChart(
"Acceleration vs Time", //chart title
"Time", //domain axis label
"Acceleration", //range axis label
createDataset(), //data
PlotOrientation.VERTICAL, //the plot orientation
true, //legend
true, //tooltips
false); //urls
return chart;
}
public static void main(String[] args) throws IOException
{
final Test demo = new Test("Test XY Line chart");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
The first 10 lines of my dataset look like this:
time x y z
0.003 -0.13 0.83 0.6
0.009 -0.12 0.83 0.61
0.012 -0.12 0.82 0.6
0.018 -0.13 0.81 0.61
0.021 -0.13 0.8 0.61
0.025 -0.12 0.8 0.61
0.033 -0.12 0.79 0.6
0.034 -0.11 0.79 0.6
0.039 -0.11 0.79 0.58
0.044 -0.11 0.77 0.57
Where your comment is - you need to first go through the elements of readNextLine where each element of the String[] will contain the value from your file for a given row (assuming your file is correctly formatted as you said). So - you need to turn these into variables. You haven't specified what format these are in, or what data type Time,X, Y and Z are.
Given that you're looking at an XY chart and your axes are labelled Time and acceleration - I'm going to guess that they're all Floating Point numbers, with Time in decimal seconds and the other variables as accelerations in the various axes. NOTE - if this assumption is wrong - you might need to use a different converter such as Integer.valueOf(), but the principle is the same.
before your while loop, set up the series that you want to add to. You'll add to them row by row within the while loop
final XYSeries seriesX = new XYSeries("X");
final XYSeries seriesY = new XYSeries("Y");
final XYSeries seriesZ = new XYSeries("Z");
within the while loop where your comment is
//add values to dataset
double Time = Double.valueOf(readNextLine[0]);
double X = Double.valueOf(readNextLine[1]);
double Y = Double.valueOf(readNextLine[2]);
double Z = Double.valueOf(readNextLine[3]);
seriesX.add(Time, X);
seriesY.add(Time, Y);
seriesZ.add(Time, Z);
and after the while loop add the 3 series to the collection before you return it:
dataset.addSeries(seriesX);
dataset.addSeries(seriesY);
dataset.addSeries(seriesZ);
Lastly - two comments
Your logic is a little weird around dataset creation. In your constructor, you create the dataset and pass it to createChart(). This is quite standard. But you then call createDataset() inline within the call to ChartFactory.createXYLineChart(, thus rendering the first creation of data pointless and doing it all again. It will work, but is wasteful and might be masking something else that you're intending the code to do.
The if check in createDataset() is redundant - you're already in a while loop based on a condition which means it will always be true.
if (readNextLine != null)
{
EDIT - added full working version to clear confusion in several comments
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import au.com.bytecode.opencsv.CSVReader;
public class Test extends ApplicationFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
XYSeriesCollection dataset;
JFreeChart chart;
final ChartPanel chartPanel;
final int chartWidth = 560;
final int chartHeight = 367;
CSVReader reader;
String[] readNextLine;
XYSeries series;
public Test(String applicationTitle) throws IOException {
super(applicationTitle);
dataset = createDataset();
chart = createChart(dataset);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(chartHeight,
chartWidth));
this.add(chartPanel);
}
public XYSeriesCollection createDataset() throws NumberFormatException,
IOException {
dataset = new XYSeriesCollection();
try {
reader = new CSVReader(new FileReader("res\\data.csv"),'\t');
// Read the header and chuck it away
readNextLine = reader.readNext();
// Set up series
final XYSeries seriesX = new XYSeries("X");
final XYSeries seriesY = new XYSeries("Y");
final XYSeries seriesZ = new XYSeries("Z");
while ((readNextLine = reader.readNext()) != null) {
// add values to dataset
double Time = Double.valueOf(readNextLine[0]);
double X = Double.valueOf(readNextLine[1]);
double Y = Double.valueOf(readNextLine[2]);
double Z = Double.valueOf(readNextLine[3]);
seriesX.add(Time, X);
seriesY.add(Time, Y);
seriesZ.add(Time, Z);
}
System.out.println(seriesX.getMaxX() + "; " + seriesX.getMaxY());
dataset.addSeries(seriesX);
dataset.addSeries(seriesY);
dataset.addSeries(seriesZ);
} catch (FileNotFoundException e) {
System.out.println("File not found!");
}
return dataset;
}
public JFreeChart createChart(XYDataset dataset)
throws NumberFormatException, IOException {
chart = ChartFactory.createXYLineChart("Acceleration vs Time", // chart
// title
"Time", // domain axis label
"Acceleration", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // the plot orientation
true, // legend
true, // tooltips
false); // urls
return chart;
}
public static void main(String[] args) throws IOException {
System.out.println("In here, to create a Test");
final Test demo = new Test("Test XY Line chart");
System.out.println("Created, pakcking");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
Output with OP supplied first 10 data points

drawing a diagram with JFreeChart

I'm working with jFreeChart on Eclipse (in Windows) and I want to draw gantt diagram for processors.
I'm doing a XY Chart
But my programme draw me a line with only P0. I want something like
draw from 0 to 10 --> P0
then from 10 to 20 --> draw H
then from 20 to 30 ---->draw wait
from 30 to 40---> draw P0
from 35 to 40 -->draw H
Code:
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
public class JFreeChartLineChartExample extends JFrame {
private static final long serialVersionUID = 1L;
public JFreeChartLineChartExample(String applicationTitle, String chartTitle) {
super(applicationTitle);
// based on the dataset we create the chart
JFreeChart pieChart = ChartFactory.createXYLineChart(chartTitle, "Time", "Processors",
createDataset(),PlotOrientation.VERTICAL, true, true, false);
// Adding chart into a chart panel
ChartPanel chartPanel = new ChartPanel(pieChart);
// settind default size
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
// add to contentPane
setContentPane(chartPanel);
}
private XYDataset createDataset() {
final XYSeries P0 = new XYSeries("P0");
P0.add(0, 1);
P0.add(10, 1);
P0.add(35, 1);
P0.add(50, 1);
P0.add(85, 1);
P0.add(110, 1);
final XYSeries P2 = new XYSeries("P2");
final XYSeries P1 = new XYSeries("P1");
final XYSeries H = new XYSeries("H");
H.add(10, 1);
H.add(20, 1);
H.add(45, 1);
H.add(100, 1);
final XYSeries wait = new XYSeries("wait");
wait.add(80, 1);
wait.add(90, 1);
wait.add(105, 1);
final XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(P0);
dataset.addSeries(P2);
dataset.addSeries(P1);
dataset.addSeries(H);
dataset.addSeries(wait);
return dataset;
}
public static void main(String[] args) {
JFreeChartLineChartExample chart = new JFreeChartLineChartExample(" GANTT ", " GANTT");
chart.pack();
chart.setVisible(true);
}
}
As far as I have understood you want to have gaps in your datasets. Your code paints a straight line from time 0 to 110 for dataset P0 because JFreeChart does not know that you want to have gaps.
To add gaps you need to add null values to your datasets.
For example P0 should be created as follows:
final XYSeries P0 = new XYSeries("P0");
P0.add(0, 1);
P0.add(10, 1);
P0.add(11, null);
P0.add(35, 1);
P0.add(50, 1);
P0.add(51, null);
P0.add(85, 1);
P0.add(110, 1);
You might also have a look at the special Gantt classes provided by JFreeChart. There are some examples in the JFreeChart demo.

draw a multiple plot with JFreechart (bar, XY)

Hello i have to make a program to display power curves, and therefore i need to display three different plots on one window.
The different kind of plots are XY (just points), bar, and XY with lines.
My problem(s) : somehow i can get only two of the charts to get drawn AND i can't change the colors of the single chart correctly.
EDIT : When i put as comment the declaration of the third chart, the second one finally gets drawn. Is it impossible to draw three charts ?
Any help will be greatly appreciated, thanks ;)
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
public class OverlaidPlot extends ApplicationFrame
{
final XYSeries series0 = new XYSeries("Graph0");
final XYSeries series1 = new XYSeries("Graph1");
final XYSeries series2 = new XYSeries("Graph2");
public OverlaidXYPlotDemo(final String title)
{
super(title);
final JFreeChart chart = createOverlaidChart();
final ChartPanel panel = new ChartPanel(chart, true, true, true, true, true);
panel.setPreferredSize(new java.awt.Dimension(800, 600));
setContentPane(panel);
}
public void addElem0(double x, double y)
{
this.series0.add(x, y);
}
public void addElem1(double x, double y)
{
this.series1.add(x, y);
}
public void addElem2(double x, double y)
{
this.series2.add(x, y);
}
private JFreeChart createOverlaidChart()
{
final NumberAxis domainAxis = new NumberAxis("Speed (m/s)");
final ValueAxis rangeAxis = new NumberAxis("Power (kw)");
// create plot ...
final IntervalXYDataset data0 = createDataset0();
final XYItemRenderer renderer0 = new XYBarRenderer(0.20);
// change "new XYBarRenderer(0.20)" to "StandardXYItemRenderer()" if you want to change type of graph
final XYPlot plot = new XYPlot(data0, domainAxis, rangeAxis, renderer0);
// add a second dataset and renderer...
final IntervalXYDataset data1 = createDataset1();
final XYLineAndShapeRenderer renderer1 = new XYLineAndShapeRenderer(false, true);
// arguments of new XYLineAndShapeRenderer are to activate or deactivate the display of points or line. Set first argument to true if you want to draw lines between the points for e.g.
plot.setDataset(1, data1);
plot.setRenderer(1, renderer1);
// add a third dataset and renderer...
final IntervalXYDataset data2 = createDataset2();
final XYLineAndShapeRenderer renderer2 = new XYLineAndShapeRenderer(true, true);
// arguments of new XYLineAndShapeRenderer are to activate or deactivate the display of points or line. Set first argument to true if you want to draw lines between the points for e.g.
plot.setDataset(1, data2);
plot.setRenderer(1, renderer2);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
NumberAxis domain = (NumberAxis) plot.getDomainAxis();/*
domain.setRange(0.00, 30);*/
domain.setTickUnit(new NumberTickUnit(0.5));
domain.setVerticalTickLabels(true);
// return a new chart containing the overlaid plot...
return new JFreeChart("Test", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
}
private IntervalXYDataset createDataset0()
{
// create dataset 0...
final XYSeriesCollection coll0 = new XYSeriesCollection(series0);
return coll0;
}
private IntervalXYDataset createDataset1()
{
// create dataset 1...
final XYSeriesCollection coll1 = new XYSeriesCollection(series1);
return coll1;
}
private IntervalXYDataset createDataset2()
{
// create dataset 2...
final XYSeriesCollection coll2 = new XYSeriesCollection(series2);
return coll2;
}
}
You have two datasets at the same index within the plot - make sure you're setting each dataset to a unique index:
plot.setDataset(2, data2);
plot.setRenderer(2, renderer2);
After changing this, I ran your example with some test data and was able to see all three data sets plotted.

Categories