Java/Swing

Last-modified: 2009-09-29 (火) 23:23:38

Componentのサイズ指定

http://java.sun.com/docs/books/tutorial/uiswing/layout/problems.html

ContainerでLayoutManagerを使っている場合で、そのContainerにaddするComponentのサイズを明示的に指定したい場合、

ComponentのsetMinimumSize, setPreferredSize, setMaximumSize に同じサイズを指定する。setSizeはLayoutManagerによって呼び出される(と思われる)ので、使っても上書きされてしまう。

明示的にサイズを指定した後に、自動計算されるサイズを有効にしたい場合は、setXxxSizeにnullを指定する(経験則)。

すでに表示されているComponentのサイズを変更した場合、そのrevalidateを呼んで、再レイアウトさせる。さらに、Componentのrepaintも呼ぶ。

レイアウトマネージャなしでレイアウト(絶対位置指定)

http://java.sun.com/docs/books/tutorial/uiswing/layout/none.html

レイアウトマネージャを作る

http://java.sun.com/docs/books/tutorial/uiswing/layout/custom.html

addLayoutComponent(String, Component) は、Container#add(String, Component)が呼ばれる場合に呼ばれ、Container#add(Component)が呼ばれた場合には呼ばれない。

layoutContainer(Container) が呼ばれたときは、レイアウト対象のComponent(Containerが持っているComponent)を取得する必要があるが、取得にはContainer#getComponents()を使うのが基本のようだ。
addLayoutComponent(String, Component)で得られたComponentをLayoutManagerで覚えておいてlayoutContainerで使うような処理にすると、Container#add(Component)されたComponentについては漏れてしまう(開発するLayoutManagerの仕様がadd(String,Component)必須とするのであれば、それでも問題なさそうだが。)

revalidate, invalidate, validate

  • 表示中のContainerのadd/removeを呼び出したら、そのあとでContainerのvalidateを呼び出す必要がある。
    (APIリファレンスのContainer#add, Container#removeの説明より)
  • 表示中のContainerのremoveを呼び出し、さらにvalidateを呼び出しても表示に反映されない場合は、そのContainerのrepaintを呼び出すと反映される場合がある(経験)
  • Componentのrevalidateを呼び出すと、コンテナ内容物階層構造の上に向かってその要求が伝達される。その伝達は、scroll paneやトップレベルコンテナなど、Componentのサイズ変更の影響を受けないContainer (ContainerのisValidateRootメソッドを呼び出して決まる) に出会うまで続く。そして、そのContainerはレイアウトされる。その結果として、revalidateされたComponentと、それに影響を受けるComponentのサイズが調整される。
    http://java.sun.com/docs/books/tutorial/uiswing/layout/howLayoutWorks.html

ここまでの話ではinvalidateが出てこない。Component/Containerの利用者がinvalidateを使う必要はない??

paint, repaint, update

http://java.sun.com/products/jfc/tsc/articles/painting/index.html

AWTの場合

  • 再描画を要求するときはreapintを呼べ
  • 描画処理はpaintに書け
  • リンクリメンタル描画(とは?)をしたければupdateをオーバーライドせよ
  • Conteiner継承クラスでpaintをオーバーライドしたら、そのpaintでsuper.paint() を必ず呼べ

動作

  • プログラムからの描画要求(repaint)があると、updateが呼ばれ、updateからpaintが呼ばれる
  • システム(OS)からの描画要求があると、(updateなしに)paintが呼ばれる

Swingの場合

  • 再描画を要求するときはreapintを呼べ
  • 描画処理はpaintで実施されるが、paintからpaintComponent, paintBorder, paintChildrenが呼ばれるため、paintComponentに描画処理を書け
  • paintComponentからはsuper.paintComponentを呼べ (UI delegateを持ったSwing componentの場合(JPanel含む))

動作

  • updateは呼ばれない