Controlクラスには、setLocationやsetSize、それにsetBoundsメソッドで位置や大きさといったものが調整できます。 それらを駆使してUIをレイアウトしてもいいのですが、 数多く作成されるControlクラスすべてをプログラマが把握して制御するには限界があります。
そのような制御はControl側で行わず、Composite側で抽象的に行うようにすると、 レイアウトが楽に行えるようになります。
SWTには、FillLayout、FormLayout、GridLayout、RowLayoutが用意されており、 それらはLayoutクラスから派生しています。
Compositeクラスには、setLayout(Layout)メソッドが用意されており、 このメソッドを通じてCompositeにレイアウトを適用することにより、 その中に格納している複数のControlを、抽象的にレイアウトすることができるようになります。
基本的なレイアウト設定クラスは、org.eclipse.swt.layoutパッケージに位置します。 各レイアウトの使い方は、別ページに記載してあります。
レイアウトは、自作することができます。 レイアウトを自作するには、Layoutクラスを継承してサブクラスを作成します。
Layoutクラスには、3つのprotectedメソッドが定義されていますが、 自作というだけあって、手が込みだすとどうしようもないほどに複雑になってしまいます。 また、開発のほとんどの場合で、既に定義されているレイアウトの組み合わせで事足りることが多いおので、 ここでは、最もシンプルな実装のサンプルを示します。 詳細は記述しませんが、もしも手の込んだ拡張をしたくなった場合には、 「レイアウトは拡張できる」ということを知っている事が大切です (実は私は手の込んだレイアウトが必要になったことがないので、詳細については知らないのです・・)。
今回は、左上から右下に、順番にcontrolを配置するという、シンプルなレイアウトを作成します。 斜めに描画するということで、SlantLayoutというネーミングにしました。 このクラスでは、computeSizeメソッドとlayoutメソッドをオーバーライドしています。 computeSizeメソッドは、このレイアウトに対する適切なサイズを算出するためのメソッドです。 layoutメソッドは、実際に、格納しているcontrolをレイアウトするためのメソッドです。
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
public class SlantLayout extends Layout {
/**
* compositeに適切なサイズを算出する
*/
protected Point computeSize(
Composite composite, int wHint, int hHint, boolean flushCache) {
// すべてのコントロールのトータルの高さと幅
Point totalPoint = new Point(0, 0);
// すべてのコントロールの高さと幅を加算
for (Control currControl : composite.getChildren()) {
Point currSize = currControl.computeSize(SWT.DEFAULT, SWT.DEFAULT);
totalPoint.x += currSize.x;
totalPoint.y += currSize.y;
}
// wHintかhHintが指定されていた場合、サイズをそれに合わせる
if (wHint != SWT.DEFAULT) {
totalPoint.x = wHint;
}
if (hHint != SWT.DEFAULT) {
totalPoint.y = hHint;
}
return totalPoint;
}
/**
* compositeをレイアウトする
*/
protected void layout(Composite composite, boolean flushCache) {
Control[] controls = composite.getChildren();
// 最初に描画するcontrolの位置は左上隅(0,0)
Point currPosi = new Point(0, 0);
// 描画したcontrolの右下に、次のcontrolを描画していく。
// compositeの広さは考慮しない。
for (int i=0 ; i < controls.length ; i++) {
Point currSize =
controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
controls[i].setBounds(
currPosi.x, currPosi.y, currSize.x, currSize.y);
currPosi.x += currSize.x;
currPosi.y += currSize.y;
}
}
}
そしてSlantLayoutを使用するコードです。
ただSlantLayoutをインスタンス化したものをsetLayoutメソッドでセットしているだけです。
この辺りの使い方は、その他のorg.eclipse.layoutパッケージに定義されているレイアウトクラスの使い方と
なんら変わりはありません。
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
public class SlantComposite extends Composite {
public SlantComposite(Composite parent) {
super(parent, SWT.NONE);
// SlantLayoutをセット
setLayout(new SlantLayout());
// ボタンを5つ作成して格納
for (int i=0 ; i<5 ; i++) {
Button button = new Button(this, SWT.NONE);
button.setText("button " + i);
}
pack();
}
}
