JFreeChart - How to remove gaps between XYBarRenderer in a TimeSeriesChart - jfreechart

I am trying to remove the gaps between the bars on a XYBarRenderer in a TimeSeriesChart. In other words, I would like to expand the bar when there is no data before and after the bar's time. Is it possible? I will really appreciate your help.
here is my code:
protected JFreeChart criarChart(XYDataset dataset){
JFreeChart chart;
chart = ChartFactory.createTimeSeriesChart(
this.getTitulo(), //titulo
this.getEixoX(), //nome do eixo-x
this.getEixoY(), //nome do eixo-y
dataset, //dados
true, //criar legenda?
true, //criar tooltips?
false); //criar URLs?
chart.setBackgroundPaint(Color.white);
XYPlot plot = (XYPlot) chart.getPlot();
plot.setOrientation(PlotOrientation.VERTICAL);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
plot.getRenderer().setSeriesPaint(0, Color.red);
plot.setRenderer(new ClusteredXYBarRenderer() {
#Override
public Paint getItemPaint(int series, int item) {
XYDataset dataset = getPlot().getDataset();
if (dataset.getYValue(series, item) >= 0.0) {
return Color.green;
}
else {
return Color.red;
}
}
}
);
XYItemRenderer renderer = plot.getRenderer();
if(renderer instanceof XYBarRenderer){
XYBarRenderer r = (XYBarRenderer)renderer;
r.setBarPainter(new StandardXYBarPainter());
r.setMargin(-20.0);
r.setShadowVisible(false);
}
//mostra o tooltip das barras do grafico
plot.getRenderer().setBaseToolTipGenerator(new StandardXYToolTipGenerator(
StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
new SimpleDateFormat("HH:mm"), new DecimalFormat("#0")));
DateAxis axis = (DateAxis) plot.getDomainAxis();
axis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
return chart;
}
I saw somewhere to change the Margin, so I tried to use:
r.setMargin(-20.0);
but didn't work.

The XYBarRenderer relies on the dataset to supply values that determine the width of the bars (see the getStartXValue() and getEndXValue() methods). It also trims the width by a percentage referred to as the 'margin'. The margin is only used if it is greater than zero, and you would specify a number like 0.20 (twenty percent). The default margin is 0.0.

Related

JFreeChart disable vertical gray areas of XYPlot

The code below plots a graph with unwanted vertical gray areas (stripes) corresponding with alternate domain ticks.
I have tried unsuccessfully to remove them from the graph to obtain a plot with white background.
I have been searching through the methods of XYPlot or NumberAxis (last try was setting to null xyplot.setDomainTickBandPaint(null); and xyplot.setRangeTickBandPaint(null);), but I have not experience enough with JFreeChart to know what method to use.
This is the code for the above graph:
public class MyPlotChart {
private static Color MetalColor = new Color(255, 152, 0);
static double[] yData = new double[] { 49.68, 49.18, 49.78, 49.65, 48.94, 50.02, 50.27};
static String[] labels = new String[] { "2021-10-28", "2021-10-29", "2021-11-01", "2021-11-02", "2021-11-03", "2021-11-04", "2021-11-05"};
public static void plot(String metal, int samples) throws IOException {
XYSeries series = new XYSeries(metal);
int i = 0;
for (i = 0; i < yData.length; i++) {
series.add(i, yData[i]);
}
XYDataset dataset = new XYSeriesCollection(series);
NumberAxis domain = new SymbolAxis(null, labels);
NumberAxis verticalAxis = new NumberAxis(null);
verticalAxis.setAutoRangeIncludesZero(false);
domain.setTickUnit(new NumberTickUnit(1.0));
domain.setMarkerBand(null);
double vericalTickUnit = (series.getMaxY() - series.getMinY()) / 5;
NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
numberFormat.setRoundingMode(RoundingMode.HALF_DOWN);
numberFormat.setMinimumFractionDigits(2);
numberFormat.setMaximumFractionDigits(2);
NumberTickUnit nt = new NumberTickUnit(vericalTickUnit, numberFormat);
verticalAxis.setTickUnit(nt);
verticalAxis.setAutoRange(true);
verticalAxis.setRange(new Range(series.getMinY()-0.1, series.getMaxY()+0.1));
verticalAxis.setTickMarksVisible(true);
verticalAxis.setTickMarkInsideLength(3f);
XYSplineRenderer r = new XYSplineRenderer(10);
r.setSeriesPaint(0, MetalColor);
r.setDefaultShapesVisible(false);
r.setSeriesStroke(0, new BasicStroke(3.0f));
XYPlot xyplot = new XYPlot(dataset, domain, verticalAxis, r);
xyplot.getDomainAxis().setVerticalTickLabels(true);
xyplot.setDomainGridlinesVisible(false);
xyplot.setBackgroundImage(null);
xyplot.setBackgroundPaint(Color.WHITE);
Font font = xyplot.getDomainAxis().getTickLabelFont();
Font fontnew = new Font(font.getName(), Font.BOLD, 14);
xyplot.getDomainAxis().setTickLabelFont(fontnew);
xyplot.getRangeAxis().setTickLabelFont(fontnew);
JFreeChart chart = new JFreeChart(xyplot);
chart.removeLegend();//Remove legend
chart.setBackgroundPaint(Color.WHITE);
String fileName = "myChart"+metal+samples+"TEST.png";
ChartUtils.saveChartAsPNG(new File(fileName), chart, 600, 600);
}
public static void main(String[] args) throws IOException {
MyPlotChart.plot("metal", 7);
}
}
As suggested in the comment, I opted to use DateAxis which do not implement alternating background and also gives more accurate treatment for tick labels when the data is time related.
I have attached the code and the plot obtained:
public class MyPlotChart {
private static Color MetalColor = new Color(255, 152, 0);
static double[] yData = new double[] { 49.68, 49.18, 49.78, 49.65, 48.94, 50.02, 50.27 };
static String[] labels = new String[] { "2021-10-28", "2021-10-29", "2021-11-01", "2021-11-02", "2021-11-03",
"2021-11-04", "2021-11-05" };
public static void plot(String metal, int samples) throws IOException, ParseException {
SimpleDateFormat dateformatyyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat dateformatdd_MM_yyyy = new SimpleDateFormat("dd-MM-yyyy");
XYSeries series = new XYSeries(metal);
for (int i = 0; i < yData.length; i++) {
Date date = dateformatyyyy_MM_dd.parse(labels[i]);
series.add(date.getTime(), yData[i]);
}
//Configure Vertical Axis
NumberAxis verticalAxis = new NumberAxis(null);
NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault());
numberFormat.setRoundingMode(RoundingMode.HALF_DOWN);
numberFormat.setMinimumFractionDigits(2);
numberFormat.setMaximumFractionDigits(2);
double vericalTickUnit = (series.getMaxY() - series.getMinY()) / 7;
NumberTickUnit nt = new NumberTickUnit(vericalTickUnit, numberFormat);
verticalAxis.setTickUnit(nt);
double percentOverRange = 0.05;// 2%
double initalRange = series.getMaxY() - series.getMinY();
double increase = initalRange * percentOverRange;
verticalAxis.setRange(new Range(series.getMinY()-increase, series.getMaxY()+increase));
verticalAxis.setAutoRange(true);
verticalAxis.setAutoRangeIncludesZero(false);
verticalAxis.setTickMarksVisible(true);
verticalAxis.setTickMarkInsideLength(3f);
//Configure Domain Axis
DateAxis domainAxis = new DateAxis(null);
domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 1, dateformatdd_MM_yyyy));
//Configure Renderer
XYSplineRenderer r = new XYSplineRenderer(10);
r.setSeriesPaint(0, MetalColor);
r.setDefaultShapesVisible(false);
r.setSeriesStroke(0, new BasicStroke(3.0f));
XYDataset dataset = new XYSeriesCollection(series);
XYPlot xyplot = new XYPlot(dataset, domainAxis, verticalAxis, r);
xyplot.getDomainAxis().setVerticalTickLabels(true);
xyplot.setDomainGridlinesVisible(false);
xyplot.setBackgroundImage(null);
xyplot.setBackgroundPaint(Color.WHITE);
Font font = xyplot.getDomainAxis().getTickLabelFont();
Font fontnew = new Font(font.getName(), Font.BOLD, 14);
xyplot.getDomainAxis().setTickLabelFont(fontnew);
xyplot.getRangeAxis().setTickLabelFont(fontnew);
JFreeChart chart = new JFreeChart(xyplot);
chart.removeLegend();// Remove legend
chart.setBackgroundPaint(Color.WHITE);
String fileName = "myChart" + metal + samples + "TEST.png";
ChartUtils.saveChartAsPNG(new File(fileName), chart, 600, 600);
}
public static void main(String[] args) throws IOException, ParseException {
MyPlotChart.plot("metal", 7);
}
}

How to draw a linechart on click in JFreeChart?

I am able to draw LineChart using JFreeChart. I would like to know how to draw linechart with legends. The place where I click should be dynamaically updated in the JFreeChart.
I have mentioned a image here to explain what I Mean.
In the Image I am able draw the black line what I want is the red line to be drawn on click. Can anybody suggest me something related to this?
Thanks in advance
Here is the sample code. In this I have 3 Series. and I am adding onclick datapoints to second series.
import com.sun.javafx.geom.Point2D;
import com.sun.javafx.scene.paint.GradientUtils.Point;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
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;
public class ChartDemo extends ApplicationFrame implements ChartMouseListener {
/**
* Creates a new demo.
*
* #param title the frame title.
*/
public static ChartPanel chartPanel = null;
public static JFreeChart chart = null;
public static XYSeries series1,series2;
public ChartDemo(final String title) {
super(title);
final XYDataset dataset = createDataset();
final JFreeChart chart = createChart(dataset);
chartPanel = new ChartPanel(chart);
chartPanel.addChartMouseListener(this);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
/**
* Creates a sample dataset.
*
* #return a sample dataset.
*/
private XYDataset createDataset() {
series1 = new XYSeries("First");
series1.add(1.0, 1.0);
series1.add(2.0, 4.0);
series1.add(3.0, 3.0);
series1.add(4.0, 5.0);
series1.add(5.0, 5.0);
series1.add(6.0, 7.0);
series1.add(7.0, 7.0);
series1.add(8.0, 8.0);
series2 = new XYSeries("Second");
series2.add(1.0, 5.0);
series2.add(2.0, 7.0);
series2.add(3.0, 6.0);
series2.add(4.0, 8.0);
series2.add(5.0, 4.0);
series2.add(6.0, 4.0);
series2.add(7.0, 2.0);
series2.add(8.0, 1.0);
final XYSeries series3 = new XYSeries("Third");
series3.add(3.0, 4.0);
series3.add(4.0, 3.0);
series3.add(5.0, 2.0);
series3.add(6.0, 3.0);
series3.add(7.0, 6.0);
series3.add(8.0, 3.0);
series3.add(9.0, 4.0);
series3.add(10.0, 3.0);
final XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series1);
dataset.addSeries(series2);
dataset.addSeries(series3);
return dataset;
}
/**
* Creates a chart.
*
* #param dataset the data for the chart.
*
* #return a chart.
*/
private JFreeChart createChart(final XYDataset dataset) {
// create the chart...
chart = ChartFactory.createXYLineChart(
"Chart Demo", // chart title
"X", // x axis label
"Y", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
final XYPlot plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.lightGray);
// plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesLinesVisible(0, false);//to disable line on the graph
renderer.setSeriesShapesVisible(2, false);//to disable shape on the graph
plot.setRenderer(renderer);
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
return chart;
}
public static void main(final String[] args)
{
final ChartDemo demo = new ChartDemo("Chart Demo");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
#Override
public void chartMouseClicked(ChartMouseEvent cme)
{
int mouseX = cme.getTrigger().getX();
int mouseY = cme.getTrigger().getY();
System.out.println("x = " + mouseX + ", y = " + mouseY);
java.awt.geom.Point2D p = chartPanel.translateScreenToJava2D(
new java.awt.Point(mouseX, mouseY));
XYPlot plot = (XYPlot) chart.getPlot();
System.out.println("Mouse clicked!!!!!");
Rectangle2D plotArea = this.chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
ValueAxis domainAxis = plot.getDomainAxis();
org.jfree.chart.ui.RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
ValueAxis rangeAxis = plot.getRangeAxis();
org.jfree.chart.ui.RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
double chartX = domainAxis.java2DToValue(p.getX(), plotArea,
domainAxisEdge);
double chartY = rangeAxis.java2DToValue(p.getY(), plotArea,
rangeAxisEdge);
System.out.println("Chart: x = " + chartX + ", y = " + chartY);
series2.add(chartX, chartY);
}
#Override
public void chartMouseMoved(ChartMouseEvent cme)
{
if(cme.getTrigger().getButton() == MouseEvent.BUTTON1)
{
}
}
}

Disable right click menu of JFreeChart

I want to disable the right click menu of JFreeChart.
I tried chartPanel.setPopupMenu(null), but it didn't work.
The following example creates a simple XYPlot with "panel.setPopupMenu( null )" disabling the popup Menu.
`
public class DisableChartPopupMenu extends ApplicationFrame {
public DisableChartPopupMenu(String title) {
super(title);
}
public static void main(final String[] args) {
(new DisableChartPopupMenu("example")).createChartNoPopupMenu();
}
public void createChartNoPopupMenu(){
final XYSeries series1 = new XYSeries("Series 1");
series1.add(10.0, 12353.3);
series1.add(20.0, 13734.4);
series1.add(30.0, 14525.3);
series1.add(40.0, 13984.3);
final XYSeriesCollection collection = new XYSeriesCollection();
collection.addSeries(series1);
final XYItemRenderer renderer1 = new StandardXYItemRenderer();
final NumberAxis rangeAxis1 = new NumberAxis("Range 1");
final XYPlot subplot1 = new XYPlot( collection, null, rangeAxis1, renderer1);
final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain"));
plot.add(subplot1, 1);
JFreeChart chart = new JFreeChart(" Demo", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
final ChartPanel panel = new ChartPanel(chart, true, true, true, false, true);
panel.setPopupMenu( null );
setContentPane(panel); pack(); setVisible(true);
}
}
`

Why are not all the Bars in my Barchart red?

Somehow i am getting some white Bars into my Histogram, any idea why?
http://www.directupload.net/file/d/3811/aybobuxf_png.htm
int number = 155897;//max number of Pixels
HistogramDataset dataset = new HistogramDataset(); //create a Histogram
dataset.setType(HistogramType.RELATIVE_FREQUENCY);
dataset.addSeries("Histogram",doubleArray,number);
String plotTitle = "Histogram";
String xaxis = "pixel";
String yaxis = "intensity";
PlotOrientation orientation = PlotOrientation.VERTICAL;//sets the vertical orientation of the Histogram
boolean show = false;
boolean toolTips = false;
boolean urls = false;
JFreeChart chart = ChartFactory.createHistogram( plotTitle, xaxis, yaxis,
dataset, orientation, show, toolTips, urls);
int widthg = 500;
int heightg = 300;
try {
ChartUtilities.saveChartAsPNG(new File("histogram41.PNG"), chart, widthg, heightg);
} catch (IOException e) {}
}}

how to change pie chart colors of JFreeChart?

how to customize the colors of JFreeChart graphic.
lets see my java code :
private StreamedContent chartImage ;
public void init(){
JFreeChart jfreechart = ChartFactory.createPieChart("title", createDataset(), true, true, false);
File chartFile = new File("dynamichart");
ChartUtilities.saveChartAsPNG(chartFile, jfreechart, 375, 300);
chartImage = new DefaultStreamedContent(new FileInputStream( chartFile), "image/png");
}
public PieDataset createDataset() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("J-2", 10);
dataset.setValue("J-1", 15);
dataset.setValue("J", 50);
dataset.setValue("J+1", 20);
dataset.setValue("J+2", 15);
return dataset;
}
html page :
<p:graphicImage id="MyImage" value="#{beanCreateImage.chartImage}" />
You can change the color of single pieces like this:
JFreeChart chart = ChartFactory.createPieChart("title", createDataset(), true, true, false);
PiePlot plot = (PiePlot) chart.getPlot();
plot.setSectionPaint("J+1", Color.black);
plot.setSectionPaint("J-1", new Color(120, 0, 120));
// or do this, if you are using an older version of JFreeChart:
//plot.setSectionPaint(1, Color.black);
//plot.setSectionPaint(3, new Color(120, 0, 120));
So with your code, all the pies are colored automatically, after my code changes, the J-1 and J+1 have a fixed color, the rest gets automatically colored.
To set the colous for a chart you can implement the DrawingSupplier inferface in this case I've used DefaultDrawingSupplier:
public class ChartDrawingSupplier extends DefaultDrawingSupplier {
public Paint[] paintSequence;
public int paintIndex;
public int fillPaintIndex;
{
paintSequence = new Paint[] {
new Color(227, 26, 28),
new Color(000,102, 204),
new Color(102,051,153),
new Color(102,51,0),
new Color(156,136,48),
new Color(153,204,102),
new Color(153,51,51),
new Color(102,51,0),
new Color(204,153,51),
new Color(0,51,0),
};
}
#Override
public Paint getNextPaint() {
Paint result
= paintSequence[paintIndex % paintSequence.length];
paintIndex++;
return result;
}
#Override
public Paint getNextFillPaint() {
Paint result
= paintSequence[fillPaintIndex % paintSequence.length];
fillPaintIndex++;
return result;
}
}
Then include this code in your `init()' method
JFreeChart jfreechart = ChartFactory.createPieChart("title", createDataset(), true, true, false);
Plot plot = jfreechart.getPlot();
plot.setDrawingSupplier(new ChartDrawingSupplier());
...
You can customize the colors according to the labels while getting the data from the dataset:
// Add custom colors
PiePlot plot = (PiePlot) chart.getPlot();
for (int i = 0; i < dataset.getItemCount(); i++) {
if(dataset.getKey(i).equals("J+1")){
plot.setSectionPaint(i, Color.black);
}
}
You can also use a switch-case statement or the one you prefer.

Resources