2011-09-25 53 views
2

所以,我使用Grahics2DJPanel對象中繪製圖形。
JPanel置於JScrollPane中,用於當我的圖形大於窗口時的情況。
但是在繪製我的圖形之後,JPanel的大小沒有變化,我無法滾動查看我的圖形的其餘部分,因此我找到最低和最左邊的點並在執行繪圖的方法中手動設置大小(方法被稱爲drawTrack())。
當我切換窗口或做其他事,使的JPanel可以重畫,我的圖形消失,所以我改寫了paint()repaint()validate()invalidate()方法,並在那裏我調用drawTrack()方法繪製在一切可能的情況下,我的圖形重繪JPanel。
問題是,當JPanel調用其中一個方法進行重繪時,我調用drawTrack()在其中重繪圖形後手動設置大小,以便我可以滾動JScrollPane並查看整個圖形。但是當我在JPanel上調用setSize()方法時,它會再次重繪,這意味着調用drawTrack()等等。
滾動條出現是因爲大小是正確的,但它會創建一個無限循環,一遍又一遍地重繪我的圖形。如果我不調用setSize()方法,我的JPanel將獲得默認大小,因此它可以放在JScrollPane的視口中,因此我無法滾動它以查看我的圖形。
有什麼建議嗎?更新JPanel的圖形時出現無限循環

+2

你能否提供[SSCCE](http://pscode.org/sscce.html)?否則,我認爲我們不能幫助你。 – Howard

+1

請參閱我的意思的例子,也是下面的SSCCE的一個例子。 –

回答

5

當您調整JPanel的大小時,會激發重繪,因此如果您在paint或paintComponent方法或這些方法中調用的某個方法中更改了大小,對我而言,您有可能導致無限循環。

解決方案:不要在paint或paintComponent方法中調整任何東西的大小。該方法僅用於繪畫,沒有別的。相反,如果您想設置JPanel的大小,請覆蓋它的getPreferredSize()方法。

這裏的 「多彩」 的例子:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class ImageReSize extends JPanel { 
    private static final int INIT_WIDTH = 400; 
    private static final int MAX_WIDTH = 1200; 

    private static final int TIMER_DELAY = 20; 
    protected static final int WIDTH_STEP = 5; 
    private int width = INIT_WIDTH; 
    private int height = INIT_WIDTH; 
    private boolean growing = true; 

    public ImageReSize() { 
     new Timer(TIMER_DELAY, new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      if (growing && width < MAX_WIDTH) { 
       width += WIDTH_STEP; 
       height += WIDTH_STEP; 
      } else { 
       growing = false; 
      } 

      if (!growing && width > INIT_WIDTH) { 
       width -= WIDTH_STEP; 
       height -= WIDTH_STEP; 
      } else { 
       growing = true; 
      } 
      // get the parent container which is the scrollpane's viewport 
      JComponent parent = (JComponent)getParent(); 
      parent.revalidate(); // let it relayout the changed size JPanel 
      parent.repaint(); // and repaint all 
     } 
     }).start(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D)g; 
     float x = (float)width/10; 
     float y = (float)height/10; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setPaint(new GradientPaint(x, 0, Color.green, 0, y, Color.black, true)); 
     g2.fillRect(0, 0, getWidth(), getHeight()); 
     g2.setPaint(new GradientPaint(0, 0, Color.blue, x, y, Color.red, true)); 
     g2.fillOval(0, 0, width, height); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(width, height); 
    } 

    private static void createAndShowUI() { 
     ImageReSize imageReSize = new ImageReSize(); 
     JFrame frame = new JFrame("ImageReSize"); 
     frame.getContentPane().add(new JScrollPane(imageReSize)); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowUI(); 
     } 
     }); 
    } 
} 
+0

用於覆蓋getPreferredSize()的+1。 – camickr

+0

@camickr:謝謝,+1對你的寶貴建議! –

3

所以我重寫了paint()方法,重繪(),驗證(),無效()方法,並在那裏我調用drawTrack()方法

這是不必要的。自定義繪畫代碼只能從paintComponent()方法中調用。

0

面臨類似問題:JPanel的paintComponent方法調用其他「方法」,它涉及Graphics中的更改,因此調用另一個paintComponent循環。

我還沒有發現移動以外的paintComponent這些「辦法」的結構方式,但發現了以下解決方案:圍繞這些「辦法」與if語句和一個布爾標誌打破循環:

boolean flag; 

@Override 
public void paintComponent(Graphics g) { 

    if (flag) { 
     gModify(); // Method that modifies Graphics g object and calls another paintComponent loop. 
     flag = !flag; // True to false - miss gModify() in the second paintComponent entry to break the loop. 
    } else { 
     flag = !flag; // False to true - allow gModify() after second paintComponent entry. 
    } 

}