左側為普通扁平圖形,右側應用漸變填充、抗鋸齒、發光邊框、投影後的立體效果:


創建半透明兼容圖像,啟用抗鋸齒,繪製白色形狀作為 Alpha 遮罩:
GraphicsConfiguration gc = g.getDeviceConfiguration();
BufferedImage img = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g2 = img.createGraphics();
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, w, h);
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(shape); // 形狀變為 Alpha=1 的區域,其餘 Alpha=0
g2.dispose();
return img; // 作為軟裁剪遮罩
在裁剪圖像上繪製垂直漸變:
g2.setPaint(new GradientPaint(0, 0, clrHi, 0, height, clrLo));
g2.fill(clipShape);
核心技巧:從粗到細描邊,顏色從內發光色漸變至外發光色,透明度逐漸增加,配合 SRC_ATOP 僅保留形狀內部區域:
private void paintBorderGlow(Graphics2D g2, int glowWidth) {
int gw = glowWidth * 2;
for (int i = gw; i >= 2; i -= 2) {
float pct = (float)(gw - i) / (gw - 1); // 0→1
Color mixHi = mixColor(clrGlowInnerHi, pct, clrGlowOuterHi, 1-pct);
Color mixLo = mixColor(clrGlowInnerLo, pct, clrGlowOuterLo, 1-pct);
g2.setPaint(new GradientPaint(0, height*0.25f, mixHi, 0, height, mixLo));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, pct));
g2.setStroke(new BasicStroke(i));
g2.draw(clipShape); // 裁剪確保僅內部可見
}
}
mixColor() 線性插值 RGBA 分量實現顏色漸變。
private void paintBorderShadow(Graphics2D g2, int shadowWidth) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int sw = shadowWidth * 2;
for (int i = sw; i >= 2; i -= 2) {
float pct = (float)(sw - i) / (sw - 1);
g2.setColor(mixColor(Color.LIGHT_GRAY, pct, Color.WHITE, 1-pct));
g2.setStroke(new BasicStroke(i));
g2.draw(clipShape); // 無 SRC_ATOP,繪製在形狀外部
}
}
調用順序:先 paintBorderShadow(外部陰影)→ 再填充漸變 → 最後 paintBorderGlow(內部發光)。
// 1. 創建形狀(圓角矩形+貝塞爾曲線)
Shape clipShape = createClipShape();
// 2. 創建軟裁剪遮罩
BufferedImage clipImage = createClipImage(clipShape);
Graphics2D g2 = clipImage.createGraphics();
// 3. 繪製陰影(最外層)
paintBorderShadow(g2, 6);
// 4. 漸變填充形狀主體
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setComposite(AlphaComposite.SrcAtop);
g2.setPaint(new GradientPaint(0, 0, clrHi, 0, height, clrLo));
g2.fill(clipShape);
// 5. 繪製發光邊框(內層)
paintBorderGlow(g2, 8);
g2.dispose();
// 6. 將最終圖像繪製到屏幕
g.drawImage(clipImage, 0, 0, null);
| API | 作用 |
|---|---|
AlphaComposite.SRC_ATOP | 僅在目標非透明區域顯示源圖像(實現內部發光裁剪) |
GradientPaint | 線性漸變填充 |
BasicStroke | 控制描邊寬度 |
RenderingHints.VALUE_ANTIALIAS_ON | 抗鋸齒,邊緣平滑 |
BufferedImage.TYPE_TRANSLUCENT | 支持 Alpha 通道的離屏圖像 |
RadialGradientPaint 實現點光源效果DropShadowFilter (SwingX) 簡化陰影實現BufferedImage 避免重繪DropShadow, Glow 效果更簡潔Java 2D 通過離屏圖像、Alpha 合成、漸變描邊疊加,能實現媲美專業設計軟件的視覺效果。掌握 SRC_ATOP 裁剪技巧與多層描邊漸變,是打造高質量 UI 的關鍵。建議在自定義組件 paintComponent() 中封裝此邏輯,構建可復用的視覺組件庫。