Change the color of jfreechart piechart - java

I want to change the color of the "pieces" of pie in my jfreechart PieChart3D, this is the code that renders the piechart:
<% response.setContentType("image/png"); %><%#page import="org.jfree.data.general.*"%><%#page import="org.jfree.chart.*"%><%#page import="org.jfree.chart.plot.*"%><%#page import="java.awt.Color" %><%
DefaultPieDataset ds = (DefaultPieDataset)session.getAttribute("usagePieOutputDataset");
JFreeChart chart = ChartFactory.createPieChart3D
(
null, // Title
ds, // Dataset
false, // Show legend
false, // Use tooltips
false // Configure chart to generate URLs?
);
chart.setBackgroundPaint(Color.WHITE);
chart.setBorderVisible(false);
PiePlot3D plot = ( PiePlot3D )chart.getPlot();
plot.setDepthFactor(0.0);
plot.setLabelGenerator(null); //null means no labels
plot.setLabelOutlinePaint(Color.LIGHT_GRAY);
plot.setLabelFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 10));
ChartUtilities.writeChartAsPNG(response.getOutputStream(), chart, 150, 144);
%>
Any help is highly appreciated.

The color for each section is normally populated from the plot's DrawingSupplier. You can override the defaults, though, by calling
PiePlot.setSectionPaint(Comparable key, Paint paint);
With, this though, you'll need to set each section manually. If you just want a different set of colors, it looks like you could implement DrawingSupplier.

You can use
Color[] colors = {Color.green, Color.red, Color.yellow .. /* size of data set */};
PieRenderer renderer = new PieRenderer(colors);
renderer.setColor(plot, ds);
and as an inner class:
static class PieRenderer
{
private Color[] color;
public PieRenderer(Color[] color)
{
this.color = color;
}
public void setColor(PiePlot plot, DefaultPieDataset dataset)
{
List <Comparable> keys = dataset.getKeys();
int aInt;
for (int i = 0; i < keys.size(); i++)
{
aInt = i % this.color.length;
plot.setSectionPaint(keys.get(i), this.color[aInt]);
}
}
}

Related

How do I remove the points in XYLineAndShapeRenderer?

I'm making an application in Java using JFreeChart which shows an XY line chart. The problem is that it shows every point of the dataset on the lines, and I don't want to display these points. Any idea on how to remove the points or make them not visible?
This is a sample screenshot:
Here is the code:
JFrame frame = new JFrame();
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesPaint(0, Color.RED);
renderer.setSeriesStroke(0, new BasicStroke(2.0f,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,
new float[] { 2.0f, 4.0f }, 0.0f));
XYDataset ds = createDataset(i, p, capacity);
JFreeChart xylineChart = ChartFactory.createXYLineChart("", "",
"", ds, PlotOrientation.VERTICAL, true, true, false);
XYPlot plot = xylineChart.getXYPlot();
plot.setDomainGridlinePaint(Color.BLACK);
plot.setRangeGridlinePaint(Color.BLACK);
plot.setBackgroundPaint(Color.WHITE);
plot.setRenderer(renderer);
ChartPanel cp = new ChartPanel(xylineChart);
frame.getContentPane().add(cp);
By default, the no-argument constructor of XYLineAndShapeRenderer "Creates a new renderer with both lines and shapes visible." To remove the points, you can
Use the alternative constructor to specify the desired combination—lines without shapes, as shown here and in ChartFactory.createXYLineChart:
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false);
Invoke setSeriesShapesVisible(), as #abhinavxeon suggests here and the author suggests here:
renderer.setSeriesShapesVisible(0, false)

Difficulty Changing background colour of JFreeChart

Im trying to change the background color to my bar chart and so far nothing seems to be working
Here is my code below:
JFreeChart expbarchart = ChartFactory.createBarChart("Monthly Expenditures", "Expenditure Type", "Amount (£)", barexp, PlotOrientation.VERTICAL, false, true, false);
ChartPanel expframe = new ChartPanel(expbarchart);
expframe.setLocation(695, 49);
expframe.setSize(641,500);
expframe.setBorder(new EtchedBorder(EtchedBorder.LOWERED, new Color(173, 216, 230), null));
graphpanel.add(expframe);
I have tried doing .setbackground() and it does not seem to work
Thanks
BarChartDemo1 shows you how to set the chart background paint:
chart.setBackgroundPaint(new Color(173, 216, 230));
It also shows you how to set a ChartTheme that you can change:
StandardChartTheme theme = new StandardChartTheme("JFree/Shadow", true);
Color color = new Color(173, 216, 230);
theme.setPlotBackgroundPaint(color);
theme.setChartBackgroundPaint(color.brighter());
ChartFactory.setChartTheme(theme);
try this and customize as per your need.
// create the chart...
JFreeChart chart = ChartFactory.createLineChart(
"# of Sales by Month", // chart title
"Month", // domain axis label
"# of Sales", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
if(subTitle != null && !subTitle.isEmpty())
chart.addSubtitle(new TextTitle(subTitle));
chart.setBackgroundPaint(Color.BLUE);
// Paint p = new GradientPaint(0, 0, Color.white, 1000, 0, Color.green);
// chart.setBackgroundPaint(p);
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setRangePannable(true);
plot.setRangeGridlinesVisible(true);
plot.setBackgroundAlpha(1);
plot.setBackgroundPaint(Color.BLUE);
// Paint p = new GradientPaint(0, 0, Color.white, 1000, 0, Color.green);
// plot.setBackgroundPaint(p);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
ChartUtilities.applyCurrentTheme(chart);
You have to use JFreeChart.getPlot().setBackgroundPaint(Color.XXXXXX); like this:
public static void main(String[] args) {
DefaultPieDataset pieDataset = new DefaultPieDataset();
pieDataset.setValue("LoggedIn" +": "+ 5, 10);
pieDataset.setValue("LoggedOut" +": "+ 8, 17);
JFreeChart jfc = ChartFactory.createPieChart("title", pieDataset, false, false, false );
jfc.getPlot().setBackgroundPaint(Color.BLUE);
ChartPanel chart = new ChartPanel(jfc);
JFrame frame = new JFrame();
frame.add(chart);
frame.pack();
frame.setVisible(true);
}
Of course, you can catch the desired color by several different methods regarding your needs, for example:
Color color1 = "anyComponent".getBackgroundColor();
and then apply
jfc.getPlot().setBackgroundPaint(color1);
I hope it helps!

JFreeChart not updating

Some background info: I'm creating a system to register lost, found and returned luggage. The amount of those 3 variable need to be in a LineChart to get a nice overview from how much luggage is lost etc. over an amount of time.
Now the problem:
When I create a LineChart and add it to a ChartPanel the LineChart represent a dataset. I've heard that when you edit/update your dataset, the chart is also automatically updated. Well I have an update button next to the chart which has to update the chart when clicked. Independent of the chart in an already existing JPanel/ChartPanel I also create a new frame which represent a ChartFrame.
When I click the update button a new frame pops-up and with the most recent data from the updated dataset. When I click it again, obviously another frame is created, but the already existing frame is also update while the chart in the JPanel isn't though they use the same dataset which is static and comes from a LineChart model.
Well here some code:
LineChartModel
//At the top of the document the dataset is initialize static
public static DefaultCategoryDataset dataset = null;
/*****************Other code omitted***********************/
/**
*
* Updates an already existing dataset
*
* #param dataset
* #return dataset
*/
public CategoryDataset updateDataset(DefaultCategoryDataset dataset) {
this.dataset = dataset;
// row keys...
final String rowLost = "Lost";
final String rowFound = "Found";
final String rowReturned = "Returned";
//Don't pay attention to this. It's setting the value for the dataset from different arrays which I know of the are filled correctly
int i = 0;
while (i < 12) {
dataset.setValue(lost[i], rowLost, type[i]);
System.out.println("There were " + lost[i]
+ " lost luggages in month: " + type[i]);
i++;
}
for (int j = 0; j < 12; j++) {
dataset.setValue(found[j], rowFound, type[j]);
System.out.println("There were " + found[j]
+ " found luggages in month: " + type[j]);
}
for (int j = 0; j < 12; j++) {
dataset.setValue(returned[j], rowReturned, type[j]);
System.out.println("There were " + returned[j]
+ " returned luggages in month: " + type[j]);
}
return dataset;
}
The LineChart Class with his constructor
LineChartModel model = new LineChartModel();
public ChartPanel chartPanel;
/**
* Creates a new demo.
*
* #param title the frame title.
*/
public LineChart(final String title, LineChartModel m) {
m = model;
m.selectRange();
m.createDataset();
final JFreeChart chart = createChart(m.dataset);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500, 270));
}
ChartController
First the params of the constructor
public ChartController(final ManCharts v, final LineChartModel m) {
view = v;
model = m;
And here the actionlistener of the button.
//Select a range by sumbitting the variables
v.date.btnSubmit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//selectRange select all the data between 2 dates but isn't important for this problem
m.selectRange(/*v.date.dateChooserFrom, v.date.dateChooserTo*/);
//updateDataset updates the dataset from the LineChartModel which is static
m.updateDataset(m.dataset);
//The data in the chart should already be updated but here I'm trying to replace the current chart by a new one
v.chart.chartPanel = new ChartPanel(v.chart.createChart(m.dataset));
//This is the new chart which does automatically update when the button is pressed
JFreeChart chart = ChartFactory.createLineChart("Something chart", "Date", "Value", m.dataset);
ChartFrame frame = new ChartFrame("New line chart", chart);
frame.setVisible(true);
}
});
I really hope someone can help and that this problem is not too complicated without having the full code.
If you need more code or something. Just say so.
Thanks in advance!
EDIT!
I think it has to do something with how I create the chart. The chart in my JPanel which is created at the start of my application is created with an edited method (this is part of my LineChart class and stands below my constructor):
/**
* Creates a sample chart.
*
* #param dataset a dataset.
*
* #return The chart.
*/
public JFreeChart createChart(final CategoryDataset dataset) {
// create the chart...
final JFreeChart chart = ChartFactory.createLineChart(
"Luggage", // chart title
"Time", // domain axis label
"Value", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.decode("#d6d9df"));
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.white);
// customise the range axis...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setAutoRangeIncludesZero(true);
// customise the renderer...
final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
//renderer.setDrawShapes(true);
renderer.setSeriesStroke(
0, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {10.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
1, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
2, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f
)
);
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
SOLVED
It had to do with another dataset that was created when clicking the submit button. So I've fixed the recreation and it's working now. Not really a chart problem, but just a problem in my model. Thanks for the help anyway!
ChartPanel implements an event listener that prompts it to repaint() itself when needed; JPanel does not. See the implementation of ChartChangeListener in chartChanged(), for example. When debugging, look for one instance of ChartPanel that shadows another or an errant use of JPanel.
Addednum Does the frame also need to be an ApplicationFrame or could it work in a JFrame?
Either is acceptable, as shown in this JFrame example or this ApplicationFrame example; both update dynamically. Note that Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

Plotting a hysteresis loop with jFreeChart

I need to draw hysteresis loops and then calculate the area closed within the loop. I am using jFreeChart.
consider the following data:
hyst[0]=0;
hyst[1]=0;
hyst[2]=0.0098;
hyst[3]=0.0196;
hyst[4]=0.0489;
hyst[5]=0.0879;
hyst[6]=0.0684;
hyst[7]=0.0489;
hyst[8]=0.0196;
hyst[9]=0.0098;
hyst[10]=0;
hyst[11]=0;
hyst[12]=0;
hyst[13]=0;
hyst[14]=0;
hyst[15]=-0.0195;
hyst[16]=-0.0488;
hyst[17]=-0.0391;
hyst[18]=-0.0195;
hyst[19]=0;
hyst[20]=0;
When I try :
public void plotHysteresis()
{
int j=0;
int i=0;
XYSeries series1 = new XYSeries("Before Treatment");
// DefaultCategoryDataset series1 = new DefaultCategoryDataset();
for(i=0;i<6;i++)
{
series1.add(j,hyst[i]);
logTextArea.append(Integer.toString(j) +" : " +Double.toString(hyst[i])+"\n");
j=j+5;
}
j=j-5;
for(;i<11;i++)
{
j=j-5;
series1.add(j,hyst[i]);
logTextArea.append(Integer.toString(j) +" : " +Double.toString(hyst[i])+"\n");
}
for(;i<16;i++)
{
j=j-5;
series1.add(j,hyst[i]);
logTextArea.append(Integer.toString(j) +" : " +Double.toString(hyst[i])+"\n");
}
for(;i<21;i++)
{
j=j+5;
series1.add(j,hyst[i]);
logTextArea.append(Integer.toString(j) +" : " +Double.toString(hyst[i])+"\n");
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series1);
JFreeChart chart = ChartFactory.createXYAreaChart(
"Hysteresis Plot", // chart title
"Pounds (lb)", // x axis label
"Distance (inches)", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
ChartPanel frame = new ChartPanel(chart);
frame.setVisible(true);
frame.setSize(plotPanel.getWidth(),plotPanel.getHeight());
plotPanel.add(frame);
plotPanel.repaint();
}
It gives me below result:
If I use :
JFreeChart chart = ChartFactory.createXYLineChart(
"Hysteresis Plot", // chart title
"Pounds (lb)", // x axis label
"Distance (inches)", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
I gives:
I need a hysteresis plot that looks like:
I guess the difference is the way points are being connected. Please guide how to obtained the desired hysteresis loop with jFreeChart and then how to calculate area enclosed.
Thanks
How can I change the line color as well the symbols representing the data points. I want all of them to be uniform.
It appears you've settled on JFreeChart for your view. Synthesizing a few other comments,
You can make the colors and shapes of your several series homogeneous by providing a DrawingSupplier, as suggested here and shown here.
You can combine the series into a GeneralPath and estimate the area as outlined here.

display numbers on pie chart

I've developed an android application to display a pie chart. I have used the achartengine library to do this.
With this code below I get the pie chart output with 3 portions labeled as mentioned in categorySeries. I want to display the percentage values on the pie diagram. How can i do this?
public static final GraphicalView getPieChartView(Context context,
CategorySeries dataset, DefaultRenderer renderer) {
checkParameters(dataset, renderer);
PieChart chart = new PieChart(dataset, renderer);
return new GraphicalView(context, chart);
}
private static void checkParameters(CategorySeries dataset,
DefaultRenderer renderer) {
if (dataset == null
|| renderer == null
|| dataset.getItemCount() != renderer
.getSeriesRendererCount()) {
throw new IllegalArgumentException(
"Dataset and renderer should be not null and the dataset number of items should be equal to the number of series renderers");
}
}
and this is my onCreate method
Bundle bundle = getIntent().getExtras();
int highc = bundle.getInt("high");
int lowc = bundle.getInt("low");
int medc = bundle.getInt("medium");
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relativestatsLayout);
TextView message = (TextView) findViewById(R.id.statText);
message.setText("\n\n\tTickets Summary");
message.setGravity(50);
//layout.addView(message);
//setContentView(message);
int[] colors = new int[] { Color.rgb(255, 0, 0),Color.rgb(220, 51,51), Color.rgb(255, 191, 0) };
DefaultRenderer renderer = buildCategoryRenderer(colors);
CategorySeries categorySeries = new CategorySeries("Tickets Chart");
categorySeries.getTitle();
categorySeries.add("critical", highc);
categorySeries.add("major ", medc);
categorySeries.add("minor ", lowc);
layout.addView(getPieChartView(this, categorySeries, renderer));
}
protected DefaultRenderer buildCategoryRenderer(int[] colors) {
DefaultRenderer renderer = new DefaultRenderer();
for (int color : colors) {
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(color);
renderer.addSeriesRenderer(r);
}
return renderer;
}
It is possible using achartengine. I have faced the same problem and found the answer now.
Use the 1.1.0-rc2 version of achart engine. You can download it here: http://www.achartengine.org/download/
This tutorial (http://wptrafficanalyzer.in/blog/android-drawing-pie-chart-using-achartengine/) helps you to create pie chart using achartengine.
Add this line to your code to display the %of distribution in the Pie chart
defaultRenderer.setDisplayValues(true);
Reference: How to set different values for Legend and Labels in piechart While I am using Chart Engine in android
Im not sure if you still have this issue. But if your pie chart is fairly simple, you should consider drawing it your self rather using a library for it.
This might help a bit.
https://github.com/blessenm/PieChartDemo

Categories