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

        }
    }

私は途方に暮れています。私は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

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

結果は次のようになります。

ここに画像の説明を入力

ご覧のとおり、小さな空き領域がありますが、これは累積された丸め誤差が原因であると思われます。すべての前の値の合計を 360 に補う arcValue で最後のセグメントを描画することで解決できます。

于 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 : これをアプレットに入れるつもりですが、このコードをアプレットに転送するなど、これを行う際に問題が発生することはありますか? あなたが私に与える推薦は、私のプログラミング時間を文字通り何時間も奪うので、私はそれらを必要とするでしょう.

お二方、どうもありがとうございました!

エド。

于 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 に答える