<更新記録>
2007年 11月 22日
作成
2008年 6月 5日
レイアウト崩れ修正

姉妹サイト検索 Web検索


Control

handle

Controlクラスは、 ハンドル番号について管理します。 例えば、LabelやButtonクラスは、Controlクラスの子クラスですが、 そのオブジェクト1つ1つに、一意なControlクラスのhandleフィールドが割り当てられています。 これは、実際のネイティブなシステムにおいて管理されるハンドル番号です。

WindowsもLinuxも、そのOSは主にC言語で記述されています。 C言語で記述されたOSのウィンドウやアイテムには、その1つ1つに、HANDLEという、数値の識別子が付けられています。 OSは、そのHANDLEという識別子で個々を区別することによって、それぞれの操作を行うことができます。 SWTのAPIは、まずOS上にアイテムを作成し、その際OSから一意に割り当てられたHANDLEをJavaVM上に取り込み、 そのHANDLEを使ってネイティブなOSに対して処理の要求を行うよう設計されています。

org.eclipse.swt.widgetsパッケージの中のほとんどのクラスは、Controlクラスのサブクラスです。

例えば、ボタンが2つあるウィンドウを作成したとします。

Buttons.java
package swt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Buttons {
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		
		Button button1 = new Button(shell, SWT.NONE);
		button1.setText("button 1");
		button1.setBounds(0, 0, 80, 30);
		Button button2 = new Button(shell, SWT.NONE);
		button2.setText("button 2");
		button2.setBounds(0, 35, 80, 30);
		
		shell.pack();
		shell.open();
		
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		
		display.dispose();
	}
}
そうすると、ButtonクラスはControlクラスのサブクラスなので、button1もbutton2も、handleフィールドを所持しています。 このhandleフィールドは、重複しないユニークなものになっているはずです。

サイズの制御

また、Controlクラスは、そのWidgetのサイズの制御という役割も担っています。 ラベルやボタンといった、Controlクラスを継承しているすべてのwidgetは、 Controlクラスのメソッドを使用することで、そのサイズや位置の取得と変更が行えます。

  • public Point getSize()
  • public void setSize(int width, int height)
  • public void setSize(Point size)

getSizeではPointオブジェクトとしてサイズを取得し、setSizeメソッドでは、個々に、もしくはPointオブジェクトによって サイズの指定を行うことができます。

他に、便利なメソッドとして、以下のものがあります。

  • public Point computeSize(int wHint, int hHint)
  • public Point computeSize(int wHint, int hHint, boolean changed)
  • public void pack()
  • public void pack(boolean changed)

これらもサイズについての操作ですが、computeSizeメソッドでは、そのcontrolが、 その内容をきちんと表示するのに最低限必要な値を返します。 この値をsetSizeメソッドで指定することで、最低限必要なcontrolのサイズにすることができますが、 その場合、packメソッドを使用します。 packメソッドは、次のコードと同じです。

Point p = computeSize(SWT.DEFAULT, SWT.DEFAULT);
setSize(p);

なので、ほとんどの場合はpackメソッドを使用します。 OSによって、Widgetのサイズ等が若干異なるので、開発段階できちんと表示されていても、 他の環境ではおかしい表示になってしまうこともあるので、直接setSizeメソッドでサイズを指定せず、 packメソッドを極力使ったほうがプリティーです。

位置の制御

Controlクラスは、位置の制御と取得を行います。

  • public Point getLocation()
  • public void setLocation(int x, int y)
  • public Rectangle getBounds()
  • public void setBounds(int x, int y, int width, int height)
  • public void setBounds(Rectangle rect)

getLocation及びsetLocationの示す座標は、そのWidgetのコンテナの左上端からの座標から、 そのWidgetの左上端までの距離を表します。 もしもcontrolがcompositeに格納されていない(つまりトップウィンドウ)場合は、 コンテナのかわりに、スクリーンからの距離になります。 setBoundsは、位置の制御に加えて、サイズの制御も同時に行います。

getLocation()が親コンテナからの相対(control-relative)位置であるのに対し、 スクリーンからの相対(display-relative)の表現があります。 これらの計算は、toControlメソッドとtoDisplayメソッドにより相互変換が可能です。

Controlの作成

controlを作成するときには、そのコンストラクタに親となるCompositeクラスのインスタンスを指定します。 controlがGUI部品の1つ1つならば、 compositeはGUI部品を入れる入れ物です。 Shellクラスも、Compositeクラスを継承しています。

ここでは、Controlクラスの子クラスの中で最も簡単なLabelクラスを例にとって、 その作り方を説明します。

Labelクラスは、簡単な文字列を表示するためのcontrolです。 コンストラクタの第1引数には親となるcompositeを指定し、 第2引数にはそのスタイルを指定します。 指定するスタイルは、SWTクラスに用意された定数から選択します。 SWTクラスに用意されている定数ならばどれでも指定できるというわけではなく、 Labelクラスの説明文で明示されているスタイルしか使用することはできません。 指定したいスタイルが複数ある場合は、or演算子'|'で区切って論理輪を指定します。 特にスタイルを指定する必要がなければ(デフォルトでよければ)、SWT.NONEのみを指定します。

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class LabelDemonstrate {
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		
		// (1)
		Label label = new Label(shell, SWT.NONE);
		label.setText("かに、ふかひれ!");
		label.pack();
		
		shell.pack();
		shell.open();
		
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		
		display.dispose();
	}
}

(1)のブロックがラベルの追加処理で、その他の部分のソースはShellで説明した内容と同じです。 (1)の処理を説明します。

まず、

Label label = new Label(shell, SWT.NONE);

この部分で、ラベルを作成しています。親コンポジット(コンテナ)には最上位ウィンドウのshellを指定しています。 そしてスタイルは、今回は何も指定しないので、SWT.NONEを指定しています。 このように、controlの作成時に親を指定することで、作成後親に格納するといった作業は行わなくて済みます。

次に、

label.setText("かに、ふかひれ!");

この部分では、ラベルで表示するテキストを設定しています。

最後に、

label.pack();

この部分で、labelのサイズを、セットしたテキストを表示するのに最低限必要なサイズに圧縮しています。
このように、コントロール(及びそれを継承した各ウィジェット)作成の基本的な流れは、

  • コンストラクタを呼び出して作成する
  • 必要であればsetTextメソッドで文字列を指定する
  • 必要であればsetSize,setLocation,setBoundsメソッド等で位置やサイズを指定する

のようになります。


Powered by VeryEasyCMS