5

我正在制作一个包含 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;
            }

        }
    }

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

我希望你能帮忙。这是完整的程序 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

4 回答 4

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

结果是这样的:

在此处输入图像描述

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

于 2013-04-13T14:37:02.930 回答
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);

和:

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

并替换行:

radius += pieValue[i].arcValue;

和:

endPoint += pieValue[i].arcValue;

结果如下:

在此处输入图像描述

别忘了打电话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);
    }
于 2013-04-13T14:52:44.510 回答
1

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

mishadoff:我可以像您在回复中提到的那样定义“权重”吗?当我想到权重时,我想象弧线开始的锚点,然后给出的值是它沿着圆的半径行进时会增加多少。这么近吗?

phcoding & mishadoff : 我打算把它放到一个 Applet 中,你认为这样做有什么问题吗,比如将这个代码转移到 Applet 中?我之所以这么问,是因为你给我的任何建议都会占用我几个小时的编程时间,而我将需要它们。

非常感谢你们!

埃德。

于 2013-04-13T15:26:38.453 回答
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);
于 2013-04-13T14:36:55.740 回答