2011-05-05 104 views
1

我一直在研究一個將自定義JComponents繪製到JLayeredPane上的程序,但是對組件上的repaint()的所有調用似乎什麼都不做,但是在重新調整窗口大小時paintComponent方法會自動調用。爲什麼paintComponent()從來沒有被repaint()調用過?

我一直在關注一些這裏給出的建議: Why is paint()/paintComponent() never called?

但沒有一個解決方案似乎解決我的問題,在美國東部時間更新Swing組件,設置組件的大小調用重繪()之前手動,調用super.paintComponent(g)在覆蓋paintComponent()並在添加新組件後在框架上調用revalidate()(儘管在這種情況下顯然沒有問題)

任何想法可以阻止該調用?在此先感謝:)

這裏是視圖和SVGElementContainer的代碼,view.setFile()是入口點,因爲它是在需要顯示新文檔時調用的。

public class View extends JLayeredPane implements SVGViewport { 

    private SVGDocument document; 
    //Array list of the SVGElementContainer components 
    private ArrayList<SVGElementContainer> elemContainers; 
    private SVGFrame frame; 
    private int elemCount; 
    private Border viewBorder; 
    private int borderWidth = 1; 

    //panels displayed on the JLayeredPane 
    private JPanel backgroundPanel; 

    /** Creates a new view */ 
    public View(SVGFrame frame) { 
     super(); 
     this.frame = frame; 
     elemCount = 0; 

     elemContainers = new ArrayList<SVGElementContainer>(); 
     viewBorder = BorderFactory.createLineBorder(Color.BLACK, borderWidth); 
    } 

    public float getViewportWidth() { 
     return getWidth(); 
    } 

    public float getViewportHeight() { 
     return getHeight(); 
    } 

    // paints all elements and adds them to the JLayeredPane 
    public void paintAllElements(){ 

     System.out.println("Painting all elements"); 

     // Paint document 
     for (SVGElement elem : document) { 
      //only paint stylable (rect, line, circle) elements 
      if (elem instanceof SVGStylable){ 
       //create a new SVGElementContainer 
       SVGElementContainer newElemCont = new SVGElementContainer(); 

       //add component to JLayeredPane 
       elemCount++; 
       this.add(newElemCont, new Integer(elemCount + 1)); 

       //set the current element within its container and calls repaint() on the component 
       System.out.println("Painting element #" + elemCount); 
       newElemCont.setElement(elem); 
       newElemCont.repaint(); 
      } 
      else { 
       System.out.println("Skip painting group element!"); 
      } 
     } 
    } 

    /** Gets the document currently being displayed by the view. */ 
    public SVGDocument getDocument() { 
     return document; 
    } 

    /** Sets the document that the view should display. 
    * 
    * @param document the document to set 
    */ 
    public void setDocument(SVGDocument document) { 
     this.document = document; 
     //paintBackground(); 
     paintAllElements(); 
     revalidate(); 
    } 

    public void revalidate(){ 
     //calls validate() on the frame in order to display newly added components 
     frame.getContentPane().validate(); 
    } 
} 

public class SVGElementContainer extends JPanel{ 

    private SVGElement elem; 

    public SVGElementContainer(){ 
     super(); 
    } 

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

     System.out.println("PAINT METHOD CALLED!"); 
     paint2D((Graphics2D) g); 
    } 

    //paint the element onto this JComponent 
    public void paint2D(Graphics2D g){ 
     if (!(elem instanceof SVGStylable)){ 
      System.out.println("Skipping non-stylable element!"); 
      return; 
     } 

     setOpaque(false); 

     Shape shape = elem.createShape(); 

     // get fill stroke and width properties 
     SVGStylable style = (SVGStylable) elem; 
     SVGPaint fillPaint = style.getFill(); 
     SVGPaint strokePaint = style.getStroke(); 
     SVGLength strokeWidth = style.getStrokeWidth(); 

     // Fill the interior of the shape 
     if (fillPaint.getPaintType() == SVGPaint.SVG_PAINTTYPE_RGBCOLOR) { 
      g.setPaint(fillPaint.getRGBColor()); 
      g.fill(shape); 
     } 

     // Stroke the outline of the shape 
     if (strokePaint.getPaintType() == SVGPaint.SVG_PAINTTYPE_RGBCOLOR) { 
      Stroke stroke = new BasicStroke(strokeWidth.getValue()); 
      g.setStroke(stroke); 
      g.setColor(strokePaint.getRGBColor()); 
      g.draw(shape); 
     } 
    } 

    public void setElement(SVGElement elem){ 
     this.elem = elem; 
     setComponentSize(); 
    } 

    private void setComponentSize(){ 

     //this.setPreferredSize(new Dimension(
     // (int)elem.getDocument().getWidth().getValue(), 
     // (int)elem.getDocument().getHeight().getValue())); 

     this.setSize(new Dimension(
       (int)elem.getDocument().getWidth().getValue(), 
       (int)elem.getDocument().getHeight().getValue())); 
    } 

} 
+2

爲了更快得到更好的幫助,請發佈[SSCCE](http://pscode.org/sscce.html)。 – 2011-05-05 19:42:53

+0

謝謝,你的描述有助於解決我的問題 - 我沒有調用'super.paintComponent(Graphics)'。 – wchargin 2011-12-12 01:43:55

回答

2

我看到你正在調用setOpaque(false)。來自setOpaque javadoc,重點是我的:

如果爲true,則該組件繪製其邊界內的每個像素。否則,組件可能無法繪製其部分或全部像素,從而允許顯示底層像素。

這可能是paintComponent()在repaint()調用期間第一次後沒有被調用的原因。 Swing可以決定組件沒有「改變」,因此不需要重繪。

+0

+1執行'setOpaque(false)'_once_,而不是調用'paintComponent()'的_every_。另請參閱[不透明度](http://java.sun.com/products/jfc/tsc/articles/painting/index。html#props) – trashgod 2011-05-05 20:00:14

+0

setOpaque()調用真的不應該在那裏,將它移動到構造器。然而,PaintComponent()從來沒有被調用過,因此也不是setOpaque(),所以這不是問題,但是由於指出了這個問題,它以後會導致問題。 – 2011-05-05 20:24:53

+0

對不起,沒有解釋我自己。我試圖說的是,如果組件不透明,那麼在repaint()調用期間(如Javadoc中所述)可能不會繪製該組件,並且這可能是您正在觀察的行爲的來源。 – Soronthar 2011-05-05 20:30:56

2

設定元件尺寸添加新組件

您的代碼後調用重繪(),調用super.paintComponent方法(g)的所述覆蓋的paintComponent()和調用重新驗證()在所述框架上之前手動這些概念錯了。

a)永遠不會調用setSize()方法。這是佈局經理的工作。您應該通過重寫像getPreferredSize()這樣的方法向佈局管理器提供提示,以返回組件的首選大小012)該提示的一點是要使用如下代碼:

panel.add(....); 
panel.revalidate(); 
panel.repaint(); 

但我真的不知道你所有的代碼是應該做的,所以我不能肯定地告訴你的代碼是有道理的。我也很奇怪你正在擴展一個JLayeredPane。

1

我可以看到擴展JPanel以獲得緩衝和UI委託,但不透明度依賴於L & F.相反,您應該從JComponent開始,併爲您的(假想的)SVGEvent實施EventListenerList管道。

相關問題