使用 Java AWT 基礎繪圖 API 繪製五星紅旗,涵蓋五角星幾何計算、坐標變換、多星佈局、Applet 繪製流程。雖然 Applet 已淘汰,但幾何算法與繪圖邏輯對 Swing/JavaFX/Canvas 繪圖仍具參考價值。
五角星可視為正五邊形五個頂點連線形成。已知外接圓半徑 `R`、圓心 `(m,n)`,利用三角函數計算 10 個頂點 (5 個外頂點、5 個內凹頂點) 坐標:
class StarModel {
// 預計算常量
private final double sin72 = Math.sin(2 * Math.PI / 5); // sin(72°)
private final double cos36 = Math.cos(Math.PI / 5); // cos(36°)
private final double cos72 = Math.cos(2 * Math.PI / 5); // cos(72°)
private final double tan36 = Math.tan(Math.PI / 5); // tan(36°)
private final double tan72 = Math.tan(2 * Math.PI / 5); // tan(72°)
// 計算 10 個 X 坐標 (順序:頂點→內凹→頂點...)
int[] calculateX(int centerX, int R) {
int[] x = new int[10];
int r = (int) (R * cos72); // 內切圓半徑
x[0] = centerX; // 頂點 0 (正上方)
x[1] = centerX - (int) (r * tan36); // 內凹 1
x[2] = centerX - (int) (R * sin72); // 頂點 2
x[3] = centerX - (int) (r * sin72 / cos36); // 內凹 3
x[4] = centerX - (int) (2 * R * sin72 * cos72); // 頂點 4
x[5] = centerX; // 頂點 5 (正下方,與 0 同 X)
x[6] = centerX + (int) (2 * R * sin72 * cos72); // 頂點 6 (對稱)
x[7] = centerX + (int) (r * sin72 / cos36); // 內凹 7
x[8] = centerX + (int) (R * sin72); // 頂點 8
x[9] = centerX + (int) (r * tan36); // 內凹 9
return x;
}
// 計算 10 個 Y 坐標
int[] calculateY(int centerY, int R) {
int[] y = new int[10];
int r = (int) (R * cos72);
y[0] = centerY; // 頂點 0
y[1] = centerY + (int) (r * tan36 * tan72); // 內凹 1
y[2] = centerY + R - r; // 頂點 2
y[3] = centerY + R + (int) (r * cos72 / cos36); // 內凹 3
y[4] = centerY + (int) (2 * R * sin72 * sin72); // 頂點 4
y[5] = centerY + R + (int) (r / cos36); // 頂點 5
y[6] = y[4]; // 對稱
y[7] = y[3];
y[8] = y[1];
y[9] = y[1];
return y;
}
}
import java.awt.*;
import java.applet.*;
public class DrawStar extends Applet {
private static final long serialVersionUID = 1L;
// 大星參數
private final int bigStarX = 200, bigStarY = 70, bigStarR = 70;
// 四小星參數 (圓心坐標、半徑)
private final int[][] smallStars = {
{310, 45, 20},
{350, 90, 20},
{355, 150, 20},
{300, 200, 20}
};
private final StarModel model = new StarModel();
@Override
public void paint(Graphics g) {
// 1. 繪製紅色背景 (旗面 3:2 比例,此處 700x400)
g.setColor(Color.RED);
g.fillRect(80, 20, 700, 400);
// 2. 設置金黃色
g.setColor(Color.YELLOW);
// 3. 繪製大五角星
g.fillPolygon(model.calculateX(bigStarX, bigStarR),
model.calculateY(bigStarY, bigStarR), 10);
// 4. 繪製四小五角星
for (int[] star : smallStars) {
g.fillPolygon(model.calculateX(star[0], star[2]),
model.calculateY(star[1], star[2]), 10);
}
}
}
import javax.swing.*;
import java.awt.*;
public class FlagFrame extends JFrame {
public FlagFrame() {
setTitle("五星紅旗 - Swing");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(880, 480);
setLocationRelativeTo(null);
add(new FlagPanel());
}
static class FlagPanel extends JPanel {
private final StarModel model = new StarModel();
// 同前座標參數...
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillRect(80, 20, 700, 400);
g2.setColor(Color.YELLOW);
g2.fillPolygon(model.calculateX(bigStarX, bigStarR), model.calculateY(bigStarY, bigStarR), 10);
for (int[] s : smallStars) {
g2.fillPolygon(model.calculateX(s[0], s[2]), model.calculateY(s[1], s[2]), 10);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new FlagFrame().setVisible(true));
}
}
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;
public class FlagFX extends Application {
@Override
public void start(Stage stage) {
Pane root = new Pane();
root.setPrefSize(880, 480);
// 紅色背景矩形
javafx.scene.shape.Rectangle bg = new javafx.scene.shape.Rectangle(80, 20, 700, 400);
bg.setFill(Color.RED);
root.getChildren().add(bg);
// 星星路徑生成工具方法
double bigX = 200, bigY = 70, bigR = 70;
double[][] small = {{310,45,20},{350,90,20},{355,150,20},{300,200,20}};
root.getChildren().add(createStar(bigX, bigY, bigR));
for (double[] s : small) root.getChildren().add(createStar(s[0], s[1], s[2]));
stage.setScene(new Scene(root));
stage.setTitle("五星紅旗 - JavaFX");
stage.show();
}
private Polygon createStar(double cx, double cy, double R) {
Polygon star = new Polygon();
star.setFill(Color.GOLD);
// 同三角函數計算 10 點加入 star.getPoints().addAll(x,y...)
return star;
}
public static void main(String[] args) { launch(args); }
}
public void saveFlagAsPng(Path outputPath) throws IOException {
int width = 880, height = 480;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 同 paintComponent 繪製邏輯...
g2.dispose();
ImageIO.write(image, "PNG", outputPath.toFile());
}
五星紅旗繪製核心在於**正五角星頂點幾何計算**與**多星相對佈局**。AWT/Applet 代碼展示基礎繪圖流程:`Graphics.fillPolygon(x[], y[], n)`。現代開發建議使用 **Swing/JavaFX/BufferedImage** 替代 Applet,配合 `Graphics2D` 抗鋸齒、標準比例計算、旋轉變換,生成高質量旗幟圖形或圖片文件。