コンポーネント


Swing コンポーネント

AWT と同様の設計で、Swing の多くの軽量コンポーネントは
そのルートに Swing コンポーネントの基本構造を提供するクラスを持ちます
AWT の Container を継承する javax.swing.JComponent クラスです
java.lang.Object
  |
  +--java.awt.Component
        |
        +--java.awt.Container
              |
              +--javax.swing.JComponent
AWT の Component クラスと異なり、コンテナを継承しているため
このクラスは、重量及び軽量コンポーネントをコンテンツペインに配置できます
コンストラクタは次のようになります

public JComponent()

このクラスのコンストラクタは、スーパークラスのコンストラクタを呼び出すだけです
その他の初期化処理を行わないため、レイアウトマネージャなどは null 状態です

多くの Swing 軽量コンポーネントはこのクラスを継承しています
それらのオブジェクトはこのクラスの便利な基本構造を利用することができます
ただし、JApplet や JFrame のような重量コンポーネントはこのクラスを継承していません

JComponent も Swing 仕様で作成されているため、「アプレット」で説明したように
直接コンポーネントを追加したり、レイアウトマネージャが設定できないのは言うまでもありません
さらに、JComponent はpaint() メソッドをオーバーライドしてはいけない
Swing では、子コンポーネントやルックアンドフィールを細分化してそれぞれに処理させるため
コンポーネント全体の描画を行う paint() メソッドは推奨されないのです

これは、Swing がルックアンドフィールのためにビュー(描画)を委譲するからです
そのため、コンポーネントに描画を再定義するには paintComponent() を使用します

protected void paintComponent(Graphics g)

g はウィンドウの描画のために使用する Graphics オブジェクトが格納されています
paint() メソッドの再定義の代わりに Swing コンポーネントはこのメソッドをオーバーライドします
import javax.swing.*;
import java.awt.*;

public class Test extends JApplet {
	public void init() {
		MyLabel lb = new MyLabel("Kitty on your lap");
		getContentPane().add(lb , BorderLayout.CENTER);
	}
	class MyLabel extends JComponent {
		String str;
		public MyLabel(String str) {
			this.str = str;
		}
		public void paintComponent(Graphics g) {
			g.drawString(str , 10 , 20);
		}
	}
}


JComponent の直接継承クラスは可視状態の透明コンポーネントになります
そのため、このプログラムの背景色は JApplet のコンテンツペインの背景色です

ただし、後ほど紹介しますが Panel クラスの Swing 版のような不可視のコンポーネントでは
レンタリングや背景の初期化などはルックアンドフィールの委譲先、またはスーパークラスが担当します
そのため、必ずpaintComponent() をオーバーライドする場合は最初に
スーパークラスの super.paintComponent() メソッドを呼び出してください
そうしなければ、委譲先がレンタリングを行うことができないのです


サイズの変更と取得

コンポーネントにはレイアウトマネージャに要求する推奨サイズや
最大サイズ、最小サイズなどを保持し、これを情報にレイアウトさせることができます

AWT で学んだように、推奨サイズは決して保証されるものではなく
最終的にコンポーネントサイズを決定するの権限を持つのはレイアウトマネージャです
しかし、サイズの値はレイアウトマネージャが利用する可能性があるため
コンポーネントはその推奨サイズや最大、最小サイズを指定するべきなのです

AWT で独自の軽量コンポーネントを作成した時は
おそらく getPreferredSize() をオーバーライドして推奨サイズを返していたはずです
ところが Swing はこれらの値をインスタンスごとに指定することができます
サイズを設定するメソッドは、次のようにサポートされています

public void setMinimumSize(Dimension minimumSize)
public void setMaximumSize(Dimension maximumSize)
public void setPreferredSize(Dimension preferredSize)

setMinimumSize() はコンポーネントの最小サイズを指定します
minimumSize にはコンポーネントサイズを表す Dimension を指定します
setMaximumSize() はコンポーネントの最大サイズを指定します
maximumSize は、コンポーネントのサイズを表す Dimension を指定します

setPreferredSize() はコンポーネントの推奨サイズを指定します
preferredSize はコンポーネントの適切なサイズを表す Dimension を指定します

コンポーネントのサイズに null が指定されている場合は
ルックアンドフィールの委譲先か、スーパークラスがサイズを計算します
同様に、サイズを取得するメソッドもサポートされています

public Dimension getMinimumSize()
public Dimension getMaximumSize()
public Dimension getPreferredSize()

getMinimumSize() は最小サイズを、getMaximumSize() は最大サイズを
getPreferredSize() は推奨サイズを返します
import javax.swing.*;
import java.awt.*;

public class Test extends JApplet {
	public void init() {
		Container contentPane = getContentPane();
		MyLabel lb = new MyLabel("Kitty on your lap" , 200 , 20);	

		contentPane.setLayout(new FlowLayout());
		contentPane.add(lb);
	}
	class MyLabel extends JComponent {
		String str;
		int height;
		public MyLabel(String str , int width , int height) {
			this.str = str;
			this.height = height;
			setPreferredSize(new Dimension(width , height + (int)(height * 0.2)));
		}
		public void paintComponent(Graphics g) {
			Dimension dim = getSize();
			g.fillRect(0 , 0 , dim.width , dim.height);
			g.setFont(new Font("Serif" , Font.PLAIN , height));
			g.setColor(Color.red);
			g.drawString(str , 10 , height);
		}
	}
}


このコンポーネントは自ら g.fillRect() を呼び出して黒く塗りつぶしています
この黒い領域が、MyLabel コンポーネントのサイズであることがわかります
FlowLayout の場合は、推奨サイズが反映されていることが確認できますね



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