2013-12-11 109 views
0

我試圖將背景圖像調整爲始終適合其駐留的JPanel。當程序運行它看起來purrfect:JPanel背景圖像調整大小後未填充面板

enter image description here

我遇到的問題是,當我調整窗口的大小,它看起來像這樣:

enter image description here

顯然,形象調整大小,但由於某種原因尚未完全繪製。這是一個更大的應用程序的一部分,但我已經分離出產生問題的代碼,最小的子集:

import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.AffineTransform; 
import java.awt.image.*; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.*; 

public class ScaleTest extends JPanel { 
static JFrame window; 
static JPanel mainPanel; 

BufferedImage originalImage; 
BufferedImage scaledImage; 

ScaleTest() { 
    setPreferredSize(new Dimension(320, 200)); 
    try { 
     originalImage = ImageIO.read(new File("cat.jpg")); 
    } catch(Exception e){} 

    addComponentListener(new ResizerListener()); 
} 

public void resize() { 
    double widthScaleFactor = getWidth()/(double)originalImage.getWidth(); 
    double heightScaleFactor = getHeight()/(double)originalImage.getHeight(); 
    double scaleFactor = (widthScaleFactor > heightScaleFactor)? heightScaleFactor : widthScaleFactor; 

    AffineTransform at = new AffineTransform(); 
    at.scale(scaleFactor, scaleFactor); 

    AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); 
    scaledImage = scaleOp.filter(originalImage, scaledImage); 

    repaint(); 
} 

@Override 
public void paintComponent(Graphics g) { 
    super.paintComponent(g); 

    g.drawImage(scaledImage, 0, 0, null); 
} 

public static void main(String[] args) { 
    javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run(){ 
      window = new JFrame("Scale Test"); 
      window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

      mainPanel = new ScaleTest(); 
      window.getContentPane().add(mainPanel); 

      window.pack(); 
      window.setLocationRelativeTo(null); // positions window in center of screen 
      window.setVisible(true); 
     } 
    }); 
} 

class ResizerListener implements ComponentListener { 
    @Override 
    public void componentResized(ComponentEvent e) { 
     resize(); 
    } 

    @Override public void componentHidden(ComponentEvent e) {} 
    @Override public void componentMoved(ComponentEvent e) {} 
    @Override public void componentShown(ComponentEvent e) {} 
} 
} 

我如何可以使圖像繪製和填充整個JPanel的?

回答

2

的問題是,所述scaledImage的大小不被在隨後的再縮放改變。

這是因爲要傳遞的scaledImage的參考filter方法,該方法是使用作爲用於產生操作的基礎上,而不是產生一個新的圖像(在合適的尺寸)

代替

scaledImage = scaleOp.filter(originalImage, scaledImage); 

使用

scaledImage = scaleOp.filter(originalImage, null); 

它的作品第一次嘗試的原因是因爲scaledImagenull

+0

謝謝!完美的工作! –

+0

做了一個很好的改變;) – MadProgrammer

+0

+1,我永遠無法理解所有那些奇特的繪畫函數是如何工作的:) – camickr

1

開頭當我嘗試使用建議更改的代碼時,發現重新繪製有點波濤洶涌。當您增加框架的大小時,在繪製面板背景(我在Windows 7上使用JDK7_10)之前,在前沿繪製黑色背景。收縮框架不會導致問題。我認爲這是因爲ComponentListener和圖像的重新創建。

沒有必要使用ComponentListener。您可以與代碼飛象以下調整圖像大小:

super.paintComponent(g); 

double widthScaleFactor = getWidth()/(double)originalImage.getWidth(); 
double heightScaleFactor = getHeight()/(double)originalImage.getHeight(); 
double scaleFactor = (widthScaleFactor > heightScaleFactor)? heightScaleFactor : widthScaleFactor; 

int width = (int)(originalImage.getWidth() * scaleFactor); 
int height = (int)(originalImage.getHeight() * scaleFactor); 

g.drawImage(originalImage, 0, 0, width, height, null); 

不知道,如果圖像質量是一樣的,因爲我不知道雙線性做什麼。

+0

我更喜歡更緊湊的解決方案,如果它的工作,我不得不說我認爲你的工作得很好。我只是做了一些科學基準測試(讀起來像是一個瘋子一樣),而且看起來速度更快,同時保持相同的質量。非常感謝你的貢獻。 –