2014-06-19 80 views
0

如果難以理解,請原諒我,但我有一個特殊問題,我需要幫助解決。我做了大量的研究,並且嘗試了很多解決方案,但是他們都沒有工作。我的問題是我有一個ImagePanel類正在擴展JPanel(代碼如下),這個類需要使用寬度和高度來縮放圖像(我正在製作一個程序,用戶可以在其中創建自定義教程,包括圖像)。當我實例化這個時,我得到一個錯誤,指出寬度和高度必須非零。我知道這是因爲佈局管理器尚未通過ImagePanel的首選大小,但我不知道如何將該大小設置爲面板。 ImagePanel位於JPanel的內部,其在JSplitPane的內部,JScrollPane的內部,JPanel的內部,JTabbedPane的內部,JSplitPane的內部,JFrame的內部。這在降低容器順序的圖形表示如下:JPanel的寬度和高度都是0(具體情況)

  1. 的JFrame(GridLayout的)
  2. 調整JSplitPane(默認SplitPane佈局)
  3. JTabbedPane中(Deault JTabbedPane的佈局)
  4. 的JPanel(GridLayout的)
  5. JScrollPane的(默認的ScrollPane佈局)
  6. 調整JSplitPane(默認SplitPane佈局)
  7. 的JPanel(GridLayout的);
  8. ImagePanel

的ImagePanel的代碼如下:

import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JPanel; 

public class ImagePanel extends JPanel{ 

    private BufferedImage i; 
    private ImageIcon miniature; 
    private Image paint = null; 

    public void createImage(String path){ 
     try {     
      i = ImageIO.read(new File(path)); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 

     if(i != null){ 
      int width = (int)((double)i.getWidth() * ((double)getWidth()/i.getWidth())); 
      int height = (int)((double)i.getHeight()*i.getHeight()/i.getWidth()*((double)this.getHeight()/i.getHeight())); 
      miniature = new ImageIcon(i.getScaledInstance(width, height, Image.SCALE_SMOOTH)); 
      paint = miniature.getImage(); 
     } 

    } 


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

     if (paint!=null){ 
      g.drawImage(paint, 0, 0, null);}  
    } 

} 

我怎樣才能得到適當的尺寸爲ImagePanel。我希望圖像更改大小爲JFrame的大小,這就是爲什麼我不只是使用setPreferedSize();

+0

爲什麼不使用'JLabel(ImageIcon)'?而不是去創建自己的'ImagePanel'。 – Muel

+0

@Muel'JLabel'不會自動重新縮放圖像,所以你需要在某個層次上做一些工作,只是說;) – MadProgrammer

+0

@MadProgrammer呵呵我忘了。我必須承認,自從我使用Swing以來已經有很多年了。 :) – Muel

回答

3

有此可能實現,第一個是允許paintComponent檢查paint的狀態和appropriatly重新調整圖像時,它是null

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

    if (i != null && paint == null){ 
     generateScaledInstance(); 
    } 
    if (paint != null) { 
     g.drawImage(paint, 0, 0, this); 
    } 
} 

這工作,因爲至少有兩種方法除非組件的尺寸大於0並且連接到本地對等體(在屏幕上),否則絕不應調用paintComponent

這不是一個好主意,因爲縮放可能需要時間,如果您可以避免它,您不想減慢繪畫過程。

您可以使用連接到ImagePanel一個ComponentListener和監測componentResized事件

addComponentListener(new ComponentAdapter() { 
    @Override 
    public void componentResized(ComponentEvent e) { 
     if (i != null) { 
      generateScaledInstance(); 
     } 
    } 
}); 

這可以被稱爲一個號碼快速連續時間,所以要小心。

在這種情況下,我傾向於使用設置爲較小的延遲的javax.swing.Timer來將更新下載到儘可能少的呼叫,例如...

private Timer resizeTimer; 
//... 
// Probably in you classes constructor 
resizeTimer = new Timer(250, new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     // Actually perform the resizing of the image... 
     generateScaledInstance(); 
    } 
}); 
// Don't want a repeating event... 
resizeTimer.setRepeats(false); 

//... 
public void componentResized(ComponentEvent evt) { 
    resizeTimer.restart(); 
} 

這使得componentResized被稱爲一個號碼快速連續的時間,但如果間隔時間超過250毫秒,則generateScaledInstance可以調用,作爲一個例子...

您還應該提供一個preferredSize默認值爲非0大小(請記住,面板的默認首選大小爲0x0)。根據不同的佈局管理器,這可以忽略不計,但通常被用作對多數佈局管理器的基礎...

+0

+1錯過那裏1.表示ScaledInstance是異步的2.重要的是測試if(resizeTimer.isRunning)then resizeTimre.restart();以避免可能的異常 – mKorbel

+0

我不想使用'getScaledInstance'。從來沒有一個例外,根據我的理解調用'restart',它會'開始'如果不運行或者重置,如果它是... – MadProgrammer

+0

Swing Timer應該在componentResized中啓動,將會重新啓動, Swing Timer的所需本地變量 – mKorbel

4

我想用圖像的JFrame的

大小而改變大小

您可以使用Darryl的Stretch Icon而不是在自己的組件中進行自定義繪畫。該圖標將根據可用空間自動調整大小。

這就是爲什麼我不使用'setPreferedSize();'。

如果你使用自定義繪畫,那麼你不應該使用setPreferredSize()。你應該重寫getPreferredSize()方法來返回圖像的大小。記住首選大小隻是佈局管理器的建議。佈局管理器可以使用或忽略大小。

如果你想在你的paintComponent(自動縮放圖像)方法,則代碼應該是:

Dimension d = getSize(); 
g.drawImage(paint, 0, 0, d.width, d.height, this); 

因此,在你的代碼,真正的挑戰(無論哪種解決方案,你選擇)是確保您正在使用佈局管理器,它將爲組件提供所有可用空間,以便圖像可以自動縮放。

+0

偏離主題,但確實你多年前曾經出現過Sun的舊Java論壇?我似乎記得你的用戶名... – Muel

+0

是的,同樣老我:) – camickr