java.awt.geom.Arc2D 是 Shape 介面實作,表示橢圓弧段。提供三種閉合類型(Arc2D.OPEN、CHORD、PIE),支援浮點(Arc2D.Float)與雙精度(Arc2D.Double)兩種精度。
| 常數 | 名稱 | 閉合方式 | 視覺效果 | 適用場景 |
|---|---|---|---|---|
Arc2D.OPEN | 開放弧 | 不閉合,僅繪製弧線 | 單純曲線 | 進度條弧、儀表盤指標 |
Arc2D.CHORD | 弦封閉弧 | 首尾兩點連直線(弦) | 弓形區域 | 月亮形狀、切片區域 |
Arc2D.PIE | 扇形封閉弧 | 首尾各連圓心形成扇形 | 餅圖切片 | 統計圖表、圓餅圖 |
// 以矩形邊界定義橢圓,角度單位為度
Arc2D.Double arc = new Arc2D.Double(
x, y, width, height, // 外接矩形(決定橢圓大小位置)
startAngle, // 起始角度(3點鐘方向為 0°,逆時針為正)
arcAngle, // 掃過角度(正數逆時針,負數順時針)
type // Arc2D.OPEN | CHORD | PIE
);
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Arc2D;
public class ArcTypesDemo extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int x = 50, y = 50, w = 200, h = 150;
int start = 45, extent = 135;
// 1. OPEN - 開放弧
Arc2D openArc = new Arc2D.Double(x, y, w, h, start, extent, Arc2D.OPEN);
g2d.setColor(Color.BLUE);
g2d.setStroke(new BasicStroke(3));
g2d.draw(openArc);
g2d.drawString("OPEN (開放弧)", x, y - 10);
// 2. CHORD - 弦封閉
y += 200;
Arc2D chordArc = new Arc2D.Double(x, y, w, h, start, extent, Arc2D.CHORD);
g2d.setColor(new Color(0x2ECC71)); // 翠綠
g2d.draw(chordArc); // 僅畫邊框
// g2d.fill(chordArc); // 填充內部
g2d.drawString("CHORD (弦封閉)", x, y - 10);
// 3. PIE - 扇形封閉
y += 200;
Arc2D pieArc = new Arc2D.Double(x, y, w, h, start, extent, Arc2D.PIE);
g2d.setColor(new Color(0xE74C3C)); // 紅
g2d.fill(pieArc); // 填充扇形
g2d.drawString("PIE (扇形)", x, y - 10);
// 4. 疊加展示:同一橢圓不同角度範圍
x = 350; y = 50;
g2d.setStroke(new BasicStroke(2));
for (int i = 0; i < 4; i++) {
Arc2D arc = new Arc2D.Double(x, y, 120, 120, i * 90, 80, Arc2D.PIE);
g2d.setColor(new Color(
(int)(Math.random() * 200) + 55,
(int)(Math.random() * 200) + 55,
(int)(Math.random() * 200) + 55
));
g2d.fill(arc);
}
g2d.drawString("PIE 疊加(模擬餅圖)", x, y - 10);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Arc2D 三種類型對比");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ArcTypesDemo());
frame.setSize(600, 700);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
public class PieChartDemo extends JPanel {
private static class Slice {
double value;
Color color;
String label;
Slice(double v, Color c, String l) { value = v; color = c; label = l; }
}
private final Slice[] slices = {
new Slice(30, new Color(0x3498DB), "Java 30%"),
new Slice(25, new Color(0xE74C3C), "Python 25%"),
new Slice(20, new Color(0x2ECC71), "JavaScript 20%"),
new Slice(15, new Color(0xF39C12), "C++ 15%"),
new Slice(10, new Color(0x9B59B6), "Go 10%")
};
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int cx = 300, cy = 250, r = 150;
double total = 0;
for (Slice s : slices) total += s.value;
double currentAngle = -90; // 從 12 點鐘方向開始
for (Slice slice : slices) {
double extent = (slice.value / total) * 360;
Arc2D.Double pie = new Arc2D.Double(
cx - r, cy - r, 2*r, 2*r,
currentAngle, extent, Arc2D.PIE
);
g2d.setColor(slice.color);
g2d.fill(pie);
g2d.setColor(Color.WHITE);
g2d.draw(pie); // 白色分隔線
// 標籤位置:扇形中點方向
double labelAngle = Math.toRadians(currentAngle + extent/2);
int lx = (int)(cx + (r * 0.7) * Math.cos(labelAngle));
int ly = (int)(cy + (r * 0.7) * Math.sin(labelAngle));
g2d.drawString(slice.label, lx - 30, ly + 5);
currentAngle += extent;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("程式語言熱門度圓餅圖");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PieChartDemo());
frame.setSize(600, 550);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
0° 為 3 點鐘方向,逆時針為正。數學慣例(順時針、Y 向上)需自行換算。x,y,width,height 定義橢圓外接矩形,非圓心座標。圓心為 (x+w/2, y+h/2)。fill() 填充內部區域,draw() 僅繪製邊框。PIE 型填充包含圓心區域。Arc2D.Float(單精度,記憶體省)vs Arc2D.Double(雙精度,計算準),一般 UI 用 Float 足夠。width/height > 0、arcAngle != 0、座標是否在可視區域內。arcAngle 取負值。RenderingHints.KEY_ANTIALIASING。