public static JFreeChart createAreaChart(double[] v1) {
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series1 = new XYSeries("First");
for (int i=0;i<v1.length;i++){
series1.add( i,v1[i]);
}
dataset.addSeries(series1);
final JFreeChart chart = ChartFactory.createXYAreaChart(
"XY Area Chart Demo",
"Domain (X)", "Range (Y)",
dataset,
PlotOrientation.VERTICAL,
true, // legend
true, // tool tips
false // URLs
);
GradientPaint gp0 = new GradientPaint(
0.0f, 0.0f, Color.red,
0.0f, 100.0f, Color.blue
);
chart.setBackgroundPaint(Color.white);
final XYPlot plot = chart.getXYPlot();
plot.getRenderer().setSeriesPaint(0, gp0);
//plot.setOutlinePaint(Color.black);
plot.setBackgroundPaint(Color.lightGray);
plot.setForegroundAlpha(0.99f);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final ValueAxis domainAxis = plot.getDomainAxis();
domainAxis.setTickMarkPaint(Color.black);
domainAxis.setLowerMargin(0.0);
domainAxis.setUpperMargin(0.0);
final ValueAxis rangeAxis = plot.getRangeAxis();
rangeAxis.setTickMarkPaint(Color.black);
rangeAxis.setAutoRange(false);
rangeAxis.setRange(-5.0, 5.0);
return chart;
}
I want something like this below. A gradient fill that switches colour slowly as we cross zero line.
I do not understand what I should put in:
GradientPaint gp0 = new GradientPaint(
0.0f, 0.0f, Color.red,
0.0f, 100.0f, Color.blue
);
The best way to do this is to have 3 shapes. One for the yellow line. Another for the green gradient, and a 3rd for the red gradient.
Then you paint the two last shapes independently.
I believe a better starting place would be a XYDifferenceRenderer have one series stay a zero so that when the second seires passes it the color will change.. Take a look at DifferenceChartDemo1 in JFreeChart. Put your two different Color GradientPaints in the constructor of the renderer.
Here is the API link the Renderer:
http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/renderer/xy/XYDifferenceRenderer.html
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 am trying to plot a real time graph using the data from serial port which arrives approx 1 sample/5 msec. So it is basically a Integer_Value Vs Time graph. Below is code to draw graph using JFreeChar (ScatterChart). In receive event handler of serial port listener I call method xySeries.add(x, y); with appropriate x and y co-ordinates.
Now plot appearance as expected is like
1. start from left end point of chart
2. Plot till right end
3. Restart from left end point of char
4. keep repeating this refresh cycles as I keep receiving continuous data over serial port.
However, I am stuck with problem #3 and #4. How to clean off the chart and restart from left end point? Also in #1 and #2 I am able to plot the points but it starts somewhere in right bottom end of chart. But I have used
xyPlot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
xyPlot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
which should ideally start from bottom left end of chart, but it does not.
Would appreciate some pointers in this direction
Thank you in advance.
public void addPoint(Number x, Number y) {
Comment:This function is called from Serial Port receive event handler that supplies X,Y values
XYItemRenderer renderer = xyPlot.getRenderer();
//System.out.println("addPoint y = " + y.doubleValue() + " minThresholdMarker" + minThresholdMarker);
if(y.doubleValue() > minThresholdMarker) {
GradientPaint gPaint = new GradientPaint(2.0f, 6.0f, Color.lightGray, 2.0f, 6.0f, Color.green);
xyPlot.setBackgroundPaint(gPaint);
renderer.setSeriesPaint(0, Color.green);
if(!countDownTimerRunning /*&& !bTimeOver */) {
timerCountDown = new Timer(1000, countDownTimeListener);
timerCountDown.setInitialDelay(0);
countDown = TREATMENT_DURATION;
countElapsed = 0;
timerCountDown.start();
countDownTimerRunning = true;
timerDispPanel.setBackground(new Color(240, 230, 140));
}
}
else {
GradientPaint gPaint = new GradientPaint(4.0f, 6.0f, Color.lightGray, 3.0f, 6.0f, Color.lightGray);
xyPlot.setBackgroundPaint(gPaint);
if(countDownTimerRunning) {
stopCountDownTimer();
}
if(patientReady) {
renderer.setSeriesPaint(0, Color.blue);
}
else {
renderer.setSeriesPaint(0, Color.black);
}
timerDispPanel.setBackground(new Color(240, 240, 240));
if(bTimeOver)
bTimeOver = false;
else
bTimeOver = true;
}
xyPlot.setRenderer(renderer);
xySeries.add(x, y);
}
private ChartPanel drawChart() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
xySeries = new XYSeries("");
xySeriesCollection.addSeries(xySeries);
JFreeChart chart = ChartFactory.createScatterPlot("Breathing Co-ordinator", "Time (ms)", "Volume (liters)", xySeriesCollection);
// Get the XY Plot from the scatter chart
xyPlot = (XYPlot) chart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
ValueAxis Xaxis = xyPlot.getDomainAxis();
Xaxis.setAutoRange(true);
Xaxis.setFixedAutoRange(80.0);
ValueAxis Yaxis = xyPlot.getRangeAxis();
Yaxis.setFixedAutoRange(6.0);
// Create the renderer
XYItemRenderer renderer = xyPlot.getRenderer();
renderer.setSeriesPaint(1, Color.blue);
NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
domain.setVerticalTickLabels(false);
NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
range.setVerticalTickLabels(false);
chartPanel_1 = new ChartPanel(chart);
chartPanel_1.setZoomAroundAnchor(true);
chartPanel_1.setMaximumDrawHeight(700);
chartPanel_1.setRefreshBuffer(true);
chartPanel_1.setLocation(0, 0);
chartPanel_1.setSize(1200, 519);
chartPanel_1.setLayout(new BorderLayout(0, 0));
NumberAxis xAxis = (NumberAxis) xyPlot.getDomainAxis();
NumberAxis yAxis = (NumberAxis) xyPlot.getRangeAxis();
yAxis.setRange(-3.0, 4.0);
xyPlot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
xyPlot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
return chartPanel_1;
}
Issue: chart.draw((Graphics2D) emffile.create(), new Rectangle(1500, 600)) throws a Nullpointerexception.
The bar chart can be generated. Please help to look into the issue.
Here my code:
CategoryDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
emffile = new EMFGraphics2D(
new File("C:\\Workspace\\eclipse\\MSReoprt\\chart.emf"),
new Dimension(1500, 600)
);
emffile.setDeviceIndependent(true);
emffile.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY
);
emffile.setRenderingHint(
RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE
);
emffile.startExport();
chart.draw((Graphics2D) emffile.create(), new Rectangle(1500, 600));
emffile.endExport();
emffile.closeStream();
Category and jfreechart method:
private CategoryDataset createDataset()
{
String series = "Availability";
String category1 = "Portal";
String category2 = "DB";
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(100, series, category1);
dataset.addValue(90, series, category2);
return dataset;
}
public JFreeChart createChart(CategoryDataset dataset)
{
FreeChart chart = ChartFactory.createBarChart
(
"Bar Chart Demo", //chart title
"Category", //domain axis label
"", //range axis label
dataset, //data
PlotOrientation.VERTICAL, //orientation
true, //include legend
true, //tooltips?
false //URLs?
);
//set the background color for the chart...
chart.setBackgroundPaint(Color.white);
//get a reference to the plot for further customisation...
CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.gray);
//set the range axis to display integers only...
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
//disable bar outlines...
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setDrawBarOutline(false);
renderer.setMaximumBarWidth(0.5);
renderer.setItemMargin(4);
//set up gradient paints for series...
GradientPaint gp0 = new GradientPaint(
0.0f, 0.0f, Color.blue,
0.0f, 0.0f, Color.MAGENTA
);
//GradientPaint gp1 = new GradientPaint(0.0f, 0.0f, Color.green,
//0.0f, 0.0f, Color.lightGray);
//GradientPaint gp2 = new GradientPaint(0.0f, 0.0f, Color.red,
//0.0f, 0.0f, Color.lightGray);
renderer.setSeriesPaint(0, gp0);
//renderer.setSeriesPaint(1, gp1);
//renderer.setSeriesPaint(2, gp2);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(
CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)
);
return chart;
}
Add stack trace:
Exception in thread "main" java.lang.NullPointerException
at org.freehep.graphicsio.emf.EMFGraphics2D.writePen(EMFGraphics2D.java:679)
at org.freehep.graphicsio.emf.EMFGraphics2D.writeStroke(EMFGraphics2D.java:575)
at org.freehep.graphicsio.AbstractVectorGraphicsIO.setStroke(AbstractVectorGraphicsIO.java:981)
at org.jfree.chart.plot.Plot.drawOutline(Plot.java:1125)
at org.jfree.chart.renderer.category.AbstractCategoryItemRenderer.drawOutline(AbstractCategoryItemRenderer.java:717)
at org.jfree.chart.plot.CategoryPlot.draw(CategoryPlot.java:3684)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1229)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1112)
at chart.BarChartDemo.export(BarChartDemo.java:61)
at chart.BarChartDemo.test(BarChartDemo.java:39)
at chart.BarChartDemo.main(BarChartDemo.java:137)
I posted this answer in the JFreeChart forum:
This looks to me like a bug in the EMFGraphics2D class. The null
pointer exception is happening at line 679:
678 private void writePen(BasicStroke stroke, Color color) throws IOException {
679 if (color.equals(penColor) && stroke.equals(getStroke()))
I didn't run the code, but presumably either 'color' or 'stroke' is
null. Since the code arrives here from line 575, it seems that
'color' is the null item (because 'stroke' isn't null, as it passed
the instance of test):
573 public void writeStroke(Stroke stroke) throws IOException {
574 if (stroke instanceof BasicStroke) {
575 writePen((BasicStroke) stroke, getColor());[/code]
Now in all the Graphics2D implementations I've seen, getColor()
never returns null (I've written test cases to explore this behaviour). But inspecting the EMFGraphics2D code, it seems as though
this is the default plus any call to setPaint() with a non-Color
argument will reset the colour to null. I think that is wrong.
I have a dynamic XYAreaChart and I want line borders to be clear because the area is all filled with a gradient color but I want the line borders to be in different color, for example my area is filled with gradient green and red color and I want the line borders to be in black color. How to do this?
Here's my code:
final XYSeries series = new XYSeries("Data");
XYSeriesCollection dataset = new XYSeriesCollection(series);
// Creation du area chart
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();
GradientPaint gp0 = new GradientPaint(0.0f, 100.0f, new Color(50, 205,
50), 0.0f, 100.0f, Color.red);
xyPlot.getRenderer().setSeriesPaint(0, gp0);
xyPlot.setForegroundAlpha(0.75f);
You should use the setSeriesOutlinePaint(int, Paint) method on the renderer.
Assuming you use a XYAreaRenderer
So something like:
XYAreaRenderer renderer = (XYAreaRenderer) xyPlot.getRenderer();
renderer.setSeriesOutlinePaint(0, Color.black);
renderer.setSeriesOutlineStroke(0, new BasicStroke(0.5f));
renderer.setOutline(true);
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);