设计思路:
1、创建图表类(各个属性)
package my;
import java.awt.Color;
import java.awt.geom.Arc2D;
public class Part
{
double amount; //该块区域所代表的数量
int degree; //根据amount经计算得到
Color color; //图例颜色
Object tag; //相关数据对象,由外部指定
Arc2D shape; //实际绘制的形状
}
2、进行图表绘制(见代码解析)【主要方法:添加扇形表+比例分配+绘制】
package my;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JPanel;
public class PieChart extends JPanel
{
//数据:pie表示一小块
private List<Part>partList =new ArrayList<>();
//color如果为null,则由内部自动分配
public void addPart(double amount,Object tag,Color color)
{
if(amount<=0)return;
Part p=new Part();
p.amount=amount;
p.tag=tag;
p.color=color;
//随机产生一种颜色
if(color==null)
{
int rgb=new Random().nextInt(0xFFFFFF);
p.color=new Color(rgb);
}
partList.add(p);
}
//根据每一个饼的数值,分配角度,自动分配颜色
private void calculate()
{
if(partList.size()==0) return;
//求出总数量
double totalAmount=0;
for(Part p : partList)
totalAmount=totalAmount+p.amount;
//分配每一份所占的角度
int totalDegrees=0;
for(int i=0;i<partList.size();i++)
{
Part p=partList.get(i);
p.degree=(int)(360*p.amount/totalAmount);
if(p.degree<3)
p.degree=3; //有的份额太小,最低分配3角度
if(i==partList.size()-1)
p.degree=360-totalDegrees; //确保占满360度
totalDegrees+=p.degree;
}
//取得一个最大的正方形
int width=this.getWidth();
int height=this.getHeight();
int w=width;
int h=width;
if(h>height)
{
h=height;
w=height;
}
Rectangle rect = new Rectangle((width-w)/2,(height-h)/2,w,h);
rect.grow(-4, -4); //往里面缩一点
//计算每一个扇形的形状
int start=90;
for(Part p : partList)
{
p.shape=new Arc2D.Double(rect, start, p.degree, Arc2D.PIE);
start=start+p.degree;
}
}
@Override
protected void paintComponent(Graphics g)
{
// TODO Auto-generated method stub
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
Graphics2D g2d = (Graphics2D) g;
// 平滑绘制 ( 反锯齿 )
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//计算每一份额的角度和扇形
this.calculate();
for(Part p:partList)
{
if(p.shape != null)
{
g2d.setPaint( p.color);
g2d.fill( p.shape );
}
}
}
}
3、添加主面板+添加扇形
package my;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyFrame extends JFrame
{
public MyFrame(String title)
{
super(title);
//内容面板
JPanel root=new JPanel();
this.setContentPane(root);
root.setLayout(new BorderLayout());
PieChart chart = new PieChart();
root.add(chart, BorderLayout.CENTER);
chart.addPart(70, "A", Color.lightGray);
chart.addPart(20, "B", Color.RED);
chart.addPart(10, "C", Color.BLUE);
}
}
4、运行程序main
package my;
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MyDemo
{
private static void createGUI()
{
// JFrame指一个窗口,构造方法的参数为窗口标题
JFrame frame = new MyFrame("比例图");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口的其他参数,如窗口大小
frame.setSize(500, 300);
// 显示窗口
frame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run()
{
createGUI();
}
});
}
}