Reputation:
I am working on a pie chart with 4 different elements. I can get the elements to appear in the JFrame but I cannot complete the pie chart circle. These are the elements:
public static class PieChart extends JComponent {
IAPieChart[] pieValue = {new IAPieChart(5, Color.green),
new IAPieChart(4, Color.orange),
new IAPieChart(3, Color.blue),
new IAPieChart(2, Color.red)
};
Now that the elements are instantiated, and loaded into the array, I use this method to paint them:
public void paintComponent(Graphics g) {
drawPie((Graphics2D) g, getBounds(), pieValue);
}
This method puts the elements together on the JFrame but only gives me about 120 degrees of the circle. :
void drawPie(Graphics2D g, Rectangle area, IAPieChart[] pieValue){
double sum = 0.0;
for (int i = 0; i < pieValue.length; i++) {
sum += pieValue[i].arcValue;
}
double endPoint = 0.0D;
int arcStart = 0;
for (int i = 0; i < pieValue.length; i++){
endPoint = (int) (endPoint * 360 / sum);
int radius = (int) (pieValue[i].arcValue * 360/ sum);
g.setColor(pieValue[i].color);
g.fillArc(area.x, area.y, area.width, area.height, arcStart , radius);
radius += pieValue[i].arcValue;
}
}
}
I'm at a loss. I have about 10 weeks expereince with Java so this is mostly trial and error. I am looking for a way to complete the circle. I reduced the values to the lowest point that would make all of the colors show. Anything larger will eliminate one color or the other.
I hope you can help. Here is the full program IAPieChart:
package iapiechart;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JFrame;
class IAPieChart{
double arcValue; // passes a value for the calculation of the arc.
Color color; // holds value for color (expressed as an integer
public IAPieChart(double value, Color color){
this.arcValue = value;
this.color = color;
}
public static class PieChart extends JComponent {
IAPieChart[] pieValue = {new IAPieChart(5, Color.green),
new IAPieChart(4, Color.orange),
new IAPieChart(3, Color.blue),
new IAPieChart(2, Color.red)
};
public void paintComponent(Graphics g) {
drawPie((Graphics2D) g, getBounds(), pieValue);
}
void drawPie(Graphics2D g, Rectangle area, IAPieChart[] pieValue){
double sum = 0.0;
for (int i = 0; i < pieValue.length; i++) {
sum += pieValue[i].arcValue;
}
double endPoint = 0.0D;
int arcStart = 0;
for (int i = 0; i < pieValue.length; i++){
endPoint = (int) (endPoint * 360 / sum);
int radius = (int) (pieValue[i].arcValue * 360/ sum);
g.setColor(pieValue[i].color);
g.fillArc(area.x, area.y, area.width, area.height, arcStart , radius);
radius += pieValue[i].arcValue;
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new PieChart());
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Upvotes: 5
Views: 1039
Reputation:
I learned that I am accumulating the wrong values from both replies from phcoding and mishadoff. With phcoding's recommendation however, I came up with additonal instances of the pieValue array. Both responses were enriching and my experience increased through your responses.
mishadoff: May I have your definition of 'weights' as you mentioned in your response? When I think of weights I imagine an anchoring point where the arc starts then the value given is how much it will increase in it's travel along the radius of the circle. Is that close?
phcoding & mishadoff : I intend to put this into an Applet do you forsee any issues with doing this, such as transfering this code into the applet? I ask because any recommendation you give me will take literally hours off of my programming time, and I am going to need them.
Thank you both very much!
Ed.
Upvotes: 1
Reputation: 21233
There is a little mixup with arcStart
calculation in the original method. It should start from the end of the previous arc. Consider this slightly modified method. The comments describe the updated lines.
void drawPie(Graphics2D g, Rectangle area, IAPieChart[] pieValue){
double sum = 0.0;
for (int i = 0; i < pieValue.length; i++) {
sum += pieValue[i].arcValue;
}
double endPoint = 0.0D;
int arcStart = 0;
for (int i = 0; i < pieValue.length; i++){
arcStart = (int) (endPoint * 360 / sum); //old line was: endPoint = (int) (endPoint * 360 / sum);
int radius = (int) (pieValue[i].arcValue * 360/ sum);
g.setColor(pieValue[i].color);
g.fillArc(area.x, area.y, area.width, area.height, arcStart , radius);
endPoint += pieValue[i].arcValue; //old line was: radius += pieValue[i].arcValue;
}
}
It replaces line:
endPoint = (int) (endPoint * 360 / sum);
with:
arcStart = (int) (endPoint * 360 / sum);
And replaces line:
radius += pieValue[i].arcValue;
with:
endPoint += pieValue[i].arcValue;
Here is the result:
Don't forget to call super.paintComponent(g);
in paintComponent()
. Also, you may want to add anti aliasing rendering hints to smooth the image a little bit, ie:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
drawPie((Graphics2D) g, getBounds(), pieValue);
}
Upvotes: 2
Reputation: 10789
If you just want to show pie chart where arc value
is a weights for segments, made a change to your draw cycle.
int arcStart = 0;
for (int i = 0; i < pieValue.length; i++){
int radius = (int) (pieValue[i].arcValue * 360.0 / sum);
g.setColor(pieValue[i].color);
g.fillArc(area.x, area.y, area.width, area.height, arcStart, radius);
arcStart += radius;
}
The result is something like this:
As you see there is a small empty area, which, I suppose, caused by accumulated rounding error. Can be solved by drawing the last segment with arcValue that complement sum of all previos to 360.
Upvotes: 4
Reputation: 608
You have
double endPoint = 0.0D;
int arcStart = 0;
for (int i = 0; i < pieValue.length; i++){
endPoint = (int) (endPoint * 360 / sum);
...
However this will always give endPoint = 0 as your multiplying by zero everytime. Try making it
endPoint += (int) (endPoint * 360 / sum);
Upvotes: 1