I am using JFreeChart to plot a line graph. The app reads in sensory data every 100 milliseconds so for a few minutes of capture it's a a lot of data. I don't plot the graph dynamically, it is static. I am using a Category plot since the axis can sometimes be decimal values, other times it can be strings, other times it can be boolean. My issue is the X axis (time) has so much data I can't make out the text:
Anyone know what I can do here to? Any tips or tricks to deal with this will be great!
private CategoryDataset createDataset() {
String series1 = "First";
String series2 = "Second";
String category1 = "Category 1";
String category2 = "Category 2";
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 0; i < time.size(); i++) {
dataset.addValue(Math.random(), series1, time.get(i));
}
return dataset;
}
private JFreeChart createChart(final CategoryDataset dataset) {
// create the chart...
final JFreeChart chart = ChartFactory.createLineChart(
"Line Chart Demo 6", // chart title
"Time", // x axis label
"RPM", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
final CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final CategoryItemRenderer renderer = (CategoryItemRenderer) plot.getRenderer();
plot.setRenderer(renderer);
return chart;
}
public void setLists(ArrayList<String> time) {
this.time = time;
final CategoryDataset dataset = createDataset();
final JFreeChart chart = createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
You can turn off the Lables and TickMarks by adding:
CategoryPlot plot = (CategoryPlot) chart.getPlot();
CategoryAxis cx = new CategoryAxis();
cx.setTickLabelsVisible(false);
cx.setTickMarksVisible(false);
plot.setDomainAxis(cx);
If you wantto display a subset of the labels (every nth value) then you will need to subclass CategoryAxis so you can overide CategoryAxis#drawCategoryLabels() andCategoryAxis#drawTickMarks()
Related
I am trying to create a score/percent/status bar using jfreechart.
The image show what it's suppose to look like.Good ScoreChart
It looks like one bar from a stack chart, so I try to adjust from there. (Do let me know if there is a better way to do this other than the stack chart)
I am seeing multiple issues doing the bar this way. I can't make the start line and end line longer. I can't put text on top of both start/end line.(I think they get chopped off) I cannot put center text in the middle of the bar either...
Here is what I got now. Bad ScoreChart
Here is the code for the bad Chart.
public JFreeChart createChart(final CategoryDataset dataset) {
final JFreeChart chart = ChartFactory.createStackedBarChart(null, null, null, dataset,
PlotOrientation.HORIZONTAL, false, false, false);
chart.setBackgroundPaint(Color.WHITE);
CategoryPlot plot = chart.getCategoryPlot();
((BarRenderer) plot.getRenderer()).setBarPainter(new StandardBarPainter());
plot.getRenderer().setSeriesPaint(0, DONUT_CHART_ORANGE);
plot.getRenderer().setSeriesPaint(1, DONUT_CHART_BLUE);
ValueAxis rangeAxis = plot.getRangeAxis();
rangeAxis.setVisible(false);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setVisible(false);
plot.setRangeGridlinesVisible(false);
plot.setBackgroundPaint(Color.WHITE);
plot.setOutlineVisible(false);
CategoryItemRenderer renderer = ((CategoryPlot) chart.getPlot()).getRenderer();
//renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelGenerator(new CustomItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);
ItemLabelPosition position = new ItemLabelPosition(ItemLabelAnchor.CENTER, TextAnchor.CENTER);
renderer.setBasePositiveItemLabelPosition(position);
Marker startMarker = new ValueMarker(0);
startMarker.setPaint(Color.black);
startMarker.setLabel("000000000");
startMarker.setStroke(new BasicStroke(1.0f));
startMarker.setLabelOffset( new RectangleInsets(UnitType.ABSOLUTE, 10,0,0,0));
startMarker.setLabelAnchor(RectangleAnchor.TOP_RIGHT) ;
startMarker.setLabelTextAnchor(TextAnchor.BASELINE_CENTER);
plot.addRangeMarker(startMarker);
Marker endMarker = new ValueMarker(1000);
endMarker.setPaint(Color.black);
endMarker.setLabel("1000");
endMarker.setStroke(new BasicStroke(1.0f));
endMarker.setLabelAnchor(RectangleAnchor.TOP);
endMarker.setLabelTextAnchor(TextAnchor.TOP_RIGHT);
plot.addRangeMarker(endMarker);
RectangleInsets chartRectangle = new RectangleInsets(35, 0, 35, 0);
chart.setPadding(chartRectangle);
return chart;
}
public CategoryDataset createDataset() {
double inValue = 775;
double[][] data = new double[][] {
{ inValue },
{ 1000- inValue },
};
return DatasetUtilities.createCategoryDataset("A", "B", data);
}
Any Idea how to move the text so they show up on top of the lines and at the center of the bar?
Can we adjust the line width at the beginning and the end?
Thanks for any idea/info.
I've created a BoxAndWhiskerRenderer plot using JFreeChart and it seems that it is automatically creating a sort of legend (see attached picutre).
Is there a way to remove the outside border of this legend and customize the font of the labels in the legend items?
Here is an example of my code:
//Get the desired BoxAndWhiskerCategoryDataset from a LinkedHashMap
BoxAndWhiskerCategoryDataset dataset = values.get(b);
//Create X axis
CategoryAxis xAxis = new CategoryAxis();
xAxis.setAxisLineVisible(false);
//Create Y axis
NumberAxis yAxis = new NumberAxis(b.getLabel());
yAxis.setAxisLineVisible(false);
yAxis.setTickLabelFont(FDFont.getFont(12f));
yAxis.setLabelFont(FDFont.getFont());
yAxis.setLabelPaint(FDPalette.secondaryText);
yAxis.setTickLabelPaint(FDPalette.secondaryText);
yAxis.setAutoRangeIncludesZero(false);
//Create renderer
BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
int count = 0;
for(Map.Entry<Integer,Color> map : clusterColor.entrySet()){
//Set color for the series (I have a previously created map which links colors and series)
renderer.setSeriesPaint(count,map.getValue());
count++;
}
renderer.setFillBox(true);
renderer.setToolTipGenerator(new BoxAndWhiskerToolTipGenerator());
CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
JFreeChart chart = new JFreeChart(plot);
chart.setBackgroundPaint(white);
chart.setBorderVisible(false);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(300, 270));
As shown here, the simplest JFreeChart constructor adds a legend by default. The code for doing so is seen here; simply substitute your desired frame, color and position.
Starting from this example, the following changes produce the chart shown below:
private void createChartPanel() {
…
JFreeChart chart = new JFreeChart("BoxAndWhiskerDemo", plot);
LegendTitle legend = chart.getLegend();
legend.setFrame(new LineBorder(Color.white, new BasicStroke(1.0f),
new RectangleInsets(1.0, 1.0, 1.0, 1.0)));
legend.setItemFont(legend.getItemFont().deriveFont(16f));
chartPanel = new ChartPanel(chart);
}
Compare to this default legend:
I have an area chart , I want to color the area of the chart which is >0 in green and the area which is <0 in red. I tried the SetSeriesPaint() method but it makes all the area chart colored by one color. How to do this?
Here's my code:
final XYSeries series = new XYSeries("Data");
XYSeriesCollection dataset = new XYSeriesCollection(series);
JFreeChart chart = ChartFactory.createXYAreaChart("Fun Meter", "", "",
dataset, PlotOrientation.VERTICAL, false, false, false);
// jframe=new ChartFrame("Fun Meter", chart);
ChartPanel CP = new ChartPanel(chart);
XYPlot xyPlot = (XYPlot) chart.getPlot();
xyPlot.getRenderer().setSeriesPaint(0, Color.red);
xyPlot.setForegroundAlpha(0.75f);
Use a XYDifferenceRenderer:
XYDifferenceRenderer r = new XYDifferenceRenderer(Color.green,Color.red, false);
plot.setRenderer(r);
im using jfree chart in my application. For my application i need to mark only first and last value of the x axis and also tick mark.
I've tried
String Male1 = "First";
String Male2 = "sec";
String Female1 = "0-4";
String Female2 = "5-18";
String Female3 = "19-45";
String Female4 = "46-64";
String Female5 = "65+";
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(202, Male1, Female1);
dataset.addValue(130, Male2, Female1);
dataset.addValue(216, Male1, Female2);
dataset.addValue(0, Male2, Female2);
dataset.addValue(248, Male1, Female3);
dataset.addValue(458, Male2, Female3);
dataset.addValue(517, Male1, Female4);
dataset.addValue(623, Male2, Female4);
dataset.addValue(1481, Male1, Female5);
dataset.addValue(680, Male2, Female5);
final JFreeChart chart = ChartFactory.createBarChart(
"", "", "", dataset,
PlotOrientation.HORIZONTAL, true, true, false);
CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.WHITE);
plot.setOutlineVisible(false);
plot.setRangeGridlinesVisible(false);
plot.setRangeGridlineStroke(new BasicStroke(0.2f));
plot.setAxisOffset(RectangleInsets.ZERO_INSETS);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setAxisLinePaint(Color.decode("#C1C1C1"));
rangeAxis.setAxisLineVisible(true);
rangeAxis.setTickMarksVisible(false);
rangeAxis.setTickMarkOutsideLength(0f);
final CategoryAxis categoryAxis = (CategoryAxis) plot.getDomainAxis();
categoryAxis.setTickMarksVisible(false);
categoryAxis.setAxisLineVisible(false);
BarRenderer br = new BarRenderer();
br.setItemMargin(0.03);
br.setShadowVisible(false);
br.setBarPainter(new StandardBarPainter());
br.setSeriesPaint(0, Color.decode("#999999"));
br.setSeriesPaint(1, Color.decode("#CCCCCC"));
chart.getCategoryPlot().setRenderer(br);
chart.removeLegend();
try {
ChartUtilities.saveChartAsPNG(new File("/media/hari/668ea9a3-d26c-4896-a2f0-756dfb532756/jfreeBarchart.png"), chart, 280, 180);
System.out.println("=====Bar chart=====");
} catch (Exception e) {
e.printStackTrace();
}
For the above code im getting
But my expectation is
Please help me to get the expected chart in jfree bar chart
If I understood correctly you want to only display two ticks (0 and 1500) and add a noticeable inside tick mark to both.
To display only two ticks you can call setTickUnit with the appropriate size argument. This size will be used by the axis object to generate the visible ticks.
To add tick marks on the inside you can call setTickMarkInsideLength.
So adding these three lines should do the trick:
rangeAxis.setTickUnit(new NumberTickUnit(1500));
rangeAxis.setTickMarksVisible(true);
rangeAxis.setTickMarkInsideLength(3f);
public class Example {
public static void main(String args[]){
/*creating timeSeriesCollection*/
TimeSeriesCollection dataset = new TimeSeriesCollection();
TimeSeries timeSeries1 = new TimeSeries("Sample 1");
timeSeries1.add(new Day(8,4, 2012), 7.0);
timeSeries1.add(new Day(19,4, 2012), 5.0);
dataset.addSeries(timeSeries1);
/*Creating the chart*/
JFreeChart chart = ChartFactory.createTimeSeriesChart("Population","Date","Population",dataset,true,true,false);
/*Altering the graph */
XYPlot plot = (XYPlot) chart.getPlot();
plot.setAxisOffset(new RectangleInsets(5.0, 10.0, 10.0, 5.0));
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
renderer.setBaseShapesVisible(true);
renderer.setBaseShapesFilled(true);
NumberAxis numberAxis = (NumberAxis)plot.getRangeAxis();
numberAxis.setRange(new Range(0,10));
DateAxis axis = (DateAxis) plot.getDomainAxis();
axis.setDateFormatOverride(new SimpleDateFormat("dd-MM-yyyy"));
axis.setAutoTickUnitSelection(false);
axis.setVerticalTickLabels(true);
/* Displaying the chart*/
ChartFrame frame = new ChartFrame("Test", chart);
frame.pack();
frame.setVisible(true);
}
}
I have written the above code which works perfectly fine but when rendering the graph it displays date which does not have values. It displays dates like 9/4/12,10/4/2012 to 18/4/2012 in y-axis which does not have a value. How can I remove the date which does not have value. And why it is behaving so?
Can any one help me please?
Try this:
public class Example1 {
public static void main(String args[]){
DefaultKeyedValues data = new DefaultKeyedValues();
data.addValue("8/4/2012" ,7.0);
data.addValue("19/04/2012",5.0);
CategoryDataset dataset = DatasetUtilities.createCategoryDataset("Population", data);
JFreeChart chart = ChartFactory.createBarChart("Population","Date","Population",dataset,PlotOrientation.VERTICAL,true,true,false);
ChartFrame frame = new ChartFrame("Test", chart);
//Switch from a Bar Rendered to a LineAndShapeRenderer so the chart looks like an XYChart
LineAndShapeRenderer renderer = new LineAndShapeRenderer();
renderer.setBaseLinesVisible(false); //TUrn of the lines
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setRenderer(0, renderer);
NumberAxis numberAxis = (NumberAxis)plot.getRangeAxis();
numberAxis.setRange(new Range(0,10));
frame.pack();
frame.setVisible(true);
}
}
Rather than using a TimeSeriesChart use a CategoryDataSet as #Dirk sugested and then switch to a LineAndShapeRenderer.
The TimeSeries is displayed continuously, which means that the dates are equally distributed along the axis, even if there is no actual value for this date. If you want only certain dates displayed, you should use some kind of CategoryDataSet.