无法完成饼图的圆圈

时间:2013-04-13 14:15:44

标签: java swing graphics2d pie-chart

我正在制作一个包含4种不同元素的饼图。我可以让元素出现在JFrame中,但我无法完成饼图圈。这些是要素:

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

        }

此方法将元素放在JFrame上,但只给出了大约120度的圆。 :

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

        }
    }

我很茫然。我用Java大约需要10周时间,所以这主要是反复试验。我正在寻找一种方法来完成这个圈子。我将值减少到可以显示所有颜色的最低点。任何更大的东西都会消除一种颜色或另一种颜色。

我希望你能提供帮助。这是完整的程序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);

        }
 }

4 个答案:

答案 0 :(得分:4)

如果您只想显示饼图,其中arc value是细分的权重,请更改您的绘图周期。

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

结果是这样的:

enter image description here

如你所见,有一个小的空白区域,我想,这是由累积的舍入错误引起的。可以通过使用arcValue绘制最后一个段来解决,该弧度补充所有previos的总和为360.

答案 1 :(得分:2)

原始方法中有arcStart计算的混合。它应该从上一个弧的结尾开始。考虑这个略微修改的方法。评论描述了更新的行。

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

它取代了行:

endPoint = (int) (endPoint * 360 / sum);

with:

arcStart = (int) (endPoint * 360 / sum);

并替换行:

radius += pieValue[i].arcValue;

with:

endPoint += pieValue[i].arcValue;

结果如下:

enter image description here

不要忘记在super.paintComponent(g);中致电paintComponent()。此外,您可能希望添加抗锯齿渲染提示以使图像平滑一点,即:

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

答案 2 :(得分:1)

你有

            double endPoint =  0.0D;
            int arcStart = 0; 
            for (int i = 0; i < pieValue.length; i++){

            endPoint = (int) (endPoint * 360 / sum);
            ...

然而,每次都会将endPoint = 0作为乘以零。尝试制作

             endPoint += (int) (endPoint * 360 / sum);

答案 3 :(得分:1)

我了解到我从phcoding和mishadoff的回复中积累了错误的值。然而,根据phcoding的建议,我想出了pieValue数组的附加实例。这两个回复都是丰富的,我的回答也增加了我的经验。

mishadoff:我可以按照您在回复中提到的“权重”定义吗?当我想到重量时,我想象一个弧开始的锚点,然后给出的值是它沿着圆的半径行进的增加量。那很近吗?

phcoding&amp; mishadoff:我打算把它放到Applet中你是否预见到这样做的任何问题,例如将这些代码转移到applet中?我问,因为你给我的任何建议都会花费我几个小时的编程时间,而我将需要它们。

非常感谢你们!