再レイアウト


コンポーネントの無効化

GUI コンポーネントは一般的には静的であることが多い
しかし、コンポーネントは常に静的であるというわけでもありません

明示的にコンポーネントのサイズを変更したり、または何らかの要因で
コンポーネントが getPreferredSize() の返す値(つまり、推奨サイズ)を変更させた場合
コンテナはコンポーネントのレイアウトを再度やりなおす必要があります

例えば、次のようなプログラムの場合は問題があります
コンポーネントが描画に必要とする推奨サイズを変更しても
再レイアウトしていないために、描画領域が少ないという失敗例です
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/*	<applet code="App67.class" width="300"height="300">
 	</applet>
*/

public class App67 extends Applet implements ItemListener {
	Label lb = new Label("Kitty on your lap");
	Font big = new Font("Serif" , Font.PLAIN , 40);
	Font small = new Font("Serif" , Font.PLAIN , 20);

	public void init() {
		setBackground(Color.white);
		lb.setFont(small);

		add(lb);
		((Checkbox)add(new Checkbox("Big"))).addItemListener(this);
	}
	public void itemStateChanged(ItemEvent e) {
		Checkbox ch = (Checkbox)e.getItemSelectable();
		if (ch.getState()) lb.setFont(big);
		else lb.setFont(small);
	}
}
アプレット

Label.setFont() を呼び出すと、Label コンポーネントは即座に再描画します
フォントサイズの変更は認められますが、コンポーネントの大きさが変わらないので
フォントがコンポーネントからはみ出てしまい、正しい動作ができません
(この問題はプラットフォームや仮想マシンのバージョンで異なります)

しかし、このときすでにコンポーネントの推奨サイズは変化しています
なので再レイアウトされてば正確に動作するのです

実は、コンポーネントには有効と無効状態というものがあり
有効状態であればレイアウトの必要はなく
無効であればレイアウトするべきであると判断されます

コンポーネントを無効化するには Component クラスの invalidate() メソッドを使用します
このメソッドは Container クラスなどにもオーバーライドされています
(ただし、独自の拡張はあまり推奨されない)

public void invalidate()

Container.invalidate() は super.invalidate() を呼び出します
独自の拡張がないかぎり、このメソッドはコンテナの階層を調べて全てを無効化します
コンポーネントを明示的に無効化させたい場合は、このように invalidate() を呼び出します

次に、無効化されたコンテナとそのコンポーネントを有効にしなければなりません
これには Component クラスの validate() メソッドを使用します
このメソッドも、Container クラスでオーバーライドされています

public void validate()

このメソッドは、コンテナ及びそのコンポーネントを有効化します
コンポーネントが無効で、コンポーネントのピアが生成されている場合
Container クラスの doLayout() を呼び出して再レイアウトします

public void doLayout()

最終的に、コンテナにコンポーネントのレイアウトを要求するのはこのメソッドです
しかし、このメソッドは直接呼び出さずに validate() から呼び出します
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/*	<applet code="App68.class" width="300"height="300">
 	</applet>
*/

public class App68 extends Applet implements ItemListener {
	Label lb = new Label("Kitty on your lap");
	Font big = new Font("Serif" , Font.PLAIN , 40);
	Font small = new Font("Serif" , Font.PLAIN , 20);

	public void init() {
		setBackground(Color.white);
		lb.setFont(small);

		add(lb);
		((Checkbox)add(new Checkbox("Big"))).addItemListener(this);
	}
	public void itemStateChanged(ItemEvent e) {
		Checkbox ch = (Checkbox)e.getItemSelectable();
		if (ch.getState()) lb.setFont(big);
		else lb.setFont(small);
		ch.invalidate();
		validate();
	}
}
アプレット

今度は、ラベルのフォントを変更するとコンポーネントが再配置されます



前のページへ戻る次のページへ