在 JPanel 繪製圖片 (drawImage) 放置 BorderLayout.NORTH,圖片不隨窗口寬度縮放,且高度異常。
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
public class ResponsiveBanner extends JPanel {
private BufferedImage banner;
private int preferredHeight = 120; // 初始期望高度
public ResponsiveBanner(String imagePath) {
setLayout(new GridBagLayout()); // 關鍵:使用 GridBagLayout
try { banner = ImageIO.read(new File(imagePath)); }
catch (Exception e) { e.printStackTrace(); }
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (banner == null) return;
int w = getWidth();
int h = getHeight();
// 保持縱橫比縮放
double scale = (double) w / banner.getWidth();
int drawH = (int) (banner.getHeight() * scale);
int y = (h - drawH) / 2; // 垂直居中
g.drawImage(banner, 0, y, w, drawH, this);
}
@Override
public Dimension getPreferredSize() {
// 返回期望高度,寬度由父容器決定
return new Dimension(400, preferredHeight);
}
public void setPreferredHeight(int h) { preferredHeight = h; revalidate(); }
}
// 使用示例
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(new ResponsiveBanner("banner.jpg"), BorderLayout.NORTH);
frame.setSize(800, 600);
frame.setVisible(true);
GridBagLayout 允許組件填充水平空間並保持首選高度。BorderLayout.NORTH 也可,但需組件正確實現 getPreferredSize()。paintComponent 中根據當前寬度 getWidth() 計算縮放比,保持縱橫比繪製。getPreferredSize() 返回固定高度、寬度較大值,讓佈局器分配空間。ImageIO.read 載入 BufferedImage,避免 Toolkit.getImage 異步載入導致繪製為空。JLabel + ImageIcon:label.setIcon(new ImageIcon(img.getScaledInstance(w, -1, Image.SCALE_SMOOTH))),需監聽 ComponentListener 手動縮放。Substance, FlatLaf 提供響應式組件。