2009-04-11 2 views
1

商品はシンプルなモデルクラスです。スイング:私のカスタムコンポーネントの塗り替えはなぜですか?

ItemComponentは、指定された場所に単純な四角形を描画するItemのビューです。 ItemComponentインスタンスの束は、アプリケーションのJFrameに追加される親コンポーネントに入れられます(今は単純なシェルです)。

ビューには2つの異なる表示スタイルがあります。私はモデルのいくつかのプロパティを調整し、場合によってはスタイルを制御する状態を変更してから、rep()を呼び出して再描画したいと思います。

私が言うことができる限り、paint()は一度しか呼び出されません。 repaint()は効果がないようです。

どういうところが間違っていますか?

私はスイングのプログラマーではないので、例から一緒にこじつけてしまったので、ここで私は理解できません。

public class ItemComponent extends JComponent implements ItemView { 

    private static final Color COLOR_FILL_NORMAL = new Color(0x008080ff); 
    private static final Color COLOR_FILL_TARGET = Color.LIGHT_GRAY; 
    private static final Color COLOR_OUTLINE = new Color(0x00333333); 

    Item item; 
    RoundRectangle2D rect; 
    State state = State.NORMAL; 
    float alpha = 1.0f; 

    public ItemComponent(Item item) { 
     this.item = item; 
     this.rect = new RoundRectangle2D.Double(0, 0, 0, 0, 5, 5); 
     item.setView(this); 
    } 

    public void setState(State state) { 
     this.state = state; 
    } 

    public void update() { 
     System.out.println("ItemComponent.update"); 
     setLocation(item.getLeft(), 1); 
     setSize(item.getWidth(), getParent().getHeight()-1); 
     rect.setRoundRect(0, 0, getWidth()-1, getHeight()-1, 5, 5); 

     repaint(); 
     //paintImmediately(getBounds()); 
    } 

    @Override 
    public void addNotify() { 
     update(); 
    } 

    @Override 
    public void paint(Graphics g) { 
     System.out.println("paint"); 

     Graphics2D g2 = (Graphics2D)g; 

     g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); 

     if (state == State.NORMAL) { 
      System.out.println("draw normal"); 
      g2.setPaint(COLOR_FILL_NORMAL); // light blue 
      g2.fill(rect); 

      g2.setPaint(COLOR_OUTLINE); 
      g2.draw(rect); 
     } 
     else if (state == State.TARGET) { 
      System.out.println("draw target"); 
      g2.setPaint(COLOR_FILL_TARGET); 
      g2.fill(rect); 

      float[] dashPattern = { 8, 5 }; 
      g2.setStroke(new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, dashPattern, 0)); 
      g.setColor(COLOR_OUTLINE); 
      g2.draw(rect); 
     } 
    } 
} 

ヒント: 私は(再描画にトレースさ)とisDisplayable()が確認されていた、そしてそれはfalseを返すの視点を発見しました。それはgetPeer()!= nullを確実にします。

私のコンポーネントにはピアがありませんか?どうしたの?それはそれ自体がアプリケーションの残りの部分に追加されるコンテナに追加されています。そしてそれは一度塗られるので、私はそれが目に見えることを知っています。

+0

ピアは、AWTコンポーネント(ピアはネイティブウィンドウシステムの実際のコンポーネントであり、コンポーネントと一緒に使用されます)の周りにあります。ほとんどのSwingコンポーネントはピアを持っていません。 なぜあなたはaddNotifyで作業していますか? –

答えて

2

これを既に見た人には謝ります。私は、すぐにそれが追加されていて、いくつかの設定を行うには、これを使用していた

@Override 
public void addNotify() { 
    update(); 
} 

:私はうっかり投稿してのビットが重要な部分を残しコードをトリムダウン。これをオーバーライドしないか、少なくともsuper.addNotify()を呼び出す必要があるか、重要な初期化が一度も発生しないことは非常に重要です。あなたのJComponentではなく、更新の自分を再描画させるrepaint()を呼び出したいでしょう

@Override 
public void addNotify() { 
    super.addNotify(); 
    update(); 
} 
+0

あなたはそれを理解してうれしいです。フォローアップをありがとう。私はまだ自分自身でJavaを学んでいます。私はこの情報を私の脳の「未来の参照」部分に追加します。 –

1

答えはどこかhereです。特にPainting in Swingの節。レンダリングコードをpaintComponent()に移動すると、JohannesRösselが示唆したように機能しませんでした。それがする時が来たときに、たとえば、 塗料()が呼び出されます - そこドキュメントはAWTの 軽量コンポーネントに適用される規則も Swingコンポーネントに適用されます。..

ペイント方法

を言うように レンダリング - そのスイング以外さらに は(塗料因子)は、次の順序で呼び出さ された3つの別々の方法を呼び出す:

protected void paintComponent(Graphics g) 
protected void paintBorder(Graphics g) 
protected void paintChildren(Graphics g) 

スイングプログラムは、 paint()をオーバーライドする代わりに paintComponent()をオーバーライドする必要があります。

0

:これにそれを変更する

は、問題を修正しました。

paint(Graphics g)を上書きするのではなく、代わりにpaintComponent(Graphics g)を上書きして、カスタムレンダリングコードを配置します。

キーの初期化が行われるため、オーバーライドされたメソッドの最初の行にsuper.paintComponent(g)を必ず呼び出してください。

重要なことは、ItemComponentが追加されているコンテナのLayoutManagerによっては、サイズを明示的に設定する必要があることです。私はあなたがupdate()メソッドでそれをやろうとしているのを見ています。サイズを設定する必要があるのは、コンポーネントを作成してコンテナに追加するコードの中に配置するのが一番良いでしょう。

あなたがしようとしていることは、paintComponent()をオーバーライドする必要があるだけです。他のすべてのオーバーライドされたメソッドを削除する必要があります。

repaint()からsetState()までを呼び出します。コンポーネントのサイズが渡された状態に依存する場合は、repaint()の直前にsetSize()を呼び出すとよいでしょう。

希望に役立ちます。

関連する問題