unable to complete the circle of a pie chart
Asked Answered
I

4

5

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);

        }
 }
Insincerity answered 13/4, 2013 at 14:15 Comment(2)
what is expected result?Endanger
+1 for sscce. See also jfreechart, which includes PiePlot with source.Grindelia
E
4

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:

enter image description here

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.

Endanger answered 13/4, 2013 at 14:37 Comment(0)
U
2

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:

enter image description here

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);
    }
Unlike answered 13/4, 2013 at 14:52 Comment(0)
P
1

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);
Pragmatic answered 13/4, 2013 at 14:36 Comment(0)
I
1

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.

Insincerity answered 13/4, 2013 at 15:26 Comment(4)
You have coded it as a JComponent and you have your paint methods so you can just add this to an applet. This tutorial can help you if you find yourself stuck. codeproject.com/Articles/34280/How-to-Write-Applet-CodePragmatic
What @Endanger means by weights is the relative sizes of each of your sections in the pie (in your case 5,4,3,2).Pragmatic
phchoding: the code project tutorial will help in other areas of my coursework. I will have to play with these sizes some to get the exact duplicate of the pie chart I am working with. I came clear after I posted what 'weights' meant. I don't feel so bad about my logic now. I feel it is relatively decent after getting your help with this exercise. Thank you for your diligent follow up with this issue. Have a great weekend!Insincerity
Your code was almost there to begin with just a few minor corrections. I'm glad it's all clear to you now :)Pragmatic

© 2022 - 2024 — McMap. All rights reserved.