Javaレイアウト・マネージャ前線に加わった最新のものが、Java 1.4リリースで追加されたSpringLayoutマネージャです。このレイアウト・マネージャを使うと、コンポーネントに「スプリング(ばね)」を付加し、そのコンポーネントを他のコンポーネントに相対的に配置できるようになります。例えばSpringLayoutを使うことで、ユーザーが画面サイズをどう変えても、ボタンが常に画面の右枠に貼りついて見えるようにすることができるのです。
他のレイアウト・マネージャと同様、SpringLayoutはコンポーネントを配置する役割を担います。コンポーネントの位置は、そのコンポーネントに関連付けられた制限で制御されます。SpringLayoutで制御された各コンポーネントには、4つの設定項目(各コンポーネントの4つのエッジに対応)を持った一つの制限があります。SpringLayoutマネージャは、これらコンポーネントの制限に関してSpringLayout.Constraintsオブジェクトをもとに動作します。これはGridBagLayoutマネージャを補完するGridBagConstraintsクラスと似たような形で動きます。つまりコンテナに追加された各コンポーネントは、SpringLayout.Constraintsオブジェクトを付加として持ち得るのです。ただし似ているのはこの点だけです。
GridBagLayoutでは普通、制限を付加してコンポーネントをコンテナに追加しますが、SpringLayoutマネージャでは通常、コンポーネントに制限を付加する必要がなく、コンポーネントを追加し、そのあと別途制限を付加する、ということができるのです。コンポーネントに制限を追加しても構わないのですが、SpringLayout.Constraintsは簡単なクラスではありません。SpringLayout.Constraintsは、(各エッジに対する)Springオブジェクトの集合であり、その各オブジェクトがコンポーネントに対して異なる制限となっているのです。これを使うには、各Spring制限を別々にSpringLayout.Constraintsに追加する必要があります。コンポーネントの、ある一つのエッジに特定の制限を設定することで、SpringLayout.Constraintsに制限が「追加」されます。SpringLayoutの4つの定数、EAST,WEST,NORTH、SOUTHを使ってSpringLayout.ConstraintsのsetContraints(String edge, Spring spring)メソッドを呼びます。ここでStringは定数の一つです。例えばコンテナ上部の左にコンポーネントを追加したいならば、一定サイズの2つのスプリングを設定、その2つを組み合わせ、その組み合わせたものを付加して、そのコンポーネントをコンテナに追加します。リスト1にこれを示します。
リスト1 SpringLayoutを使う
Component left = ...;
SpringLayout layout = new SpringLayout();
JPanel panel = new JPanel(layout);
Spring xPad = Spring.constant(5);
Spring yPad = Spring.constant(25);
SpringLayout.Constraints constraint = new SpringLayout.Constraints();
constraint.setConstraint(SpringLayout.WEST, xPad);
constraint.setConstraint(SpringLayout.NORTH, yPad);
contentPane.add(left, constraint);
|
これはそれほど難しくないように見えるかもしれませんが、その次のコンポーネントを、最初に置いたコンポーネントの右や下に追加しようとすると、もっと難しくなってきます。コンポーネントを単にn ピクセル単位の指定で追加することはできず、先に置いたコンポーネントのエッジに、実際にパディングを追加しなければならないのです。先に置いたコンポーネントのエッジを見つけるにはgetConstraint()を使ってレイアウト・マネージャに問い合わせます。具体的にはlayout.getConstraint(SpringLayout.EAST, left)のようにそのコンポーネントと必要なエッジとをレイアウト・マネージャに渡し、最初のコンポーネントの右エッジ位置を取得するのです。そうした後、必要なパディングを追加し、そのパディングを後から追加するコンポーネントのエッジに付加します。これをリスト2に示します。
リスト2 SpringLayoutで2番目のコンポーネントを追加する
Component right = ...;
Spring rightSideOfLeft = layout.getConstraint(SpringLayout.EAST, left);
Spring pad = Spring.constant(20);
Spring leftEdgeOfRight = Spring.sum(rightSideOfLeft, pad);
constraint = new SpringLayout.Constraints();
constraint.setConstraint(SpringLayout.WEST, leftEdgeOfRight);
constraint.setConstraint(SpringLayout.NORTH, yPad);
contentPane.add(right, constraint);
|
SpringLayoutでputConstraint()を使う
このやり方で全く問題なく動くのですが、コンポーネントの数が増えてくると非常に手間がかかることになります。代わりの手段として中間のステップを回避する方法があります。コンポーネントを制限の付加無しに追加し、SpringLayoutのputConstraint()メソッドを使って後から各制限を別々に追加することでコンポーネントを連結するという、リスト3に示すような方法です。
リスト3 SpringLayoutで2番目のコンポーネントを追加する
public void putConstraint(String e1, Component c1, int pad, String e2, Component c2)
public void putConstraint(String e1, Component c1, Spring s, String e2, Component c2)
|
ここでは、エッジを問い合わせ、自分でパディングを追加しなくても、putConstraint()へのコールがその二つを処理します。これをお見せするためにリスト4では、リスト3のコンポーネント制限と同じコンポーネント制限を右のコンポーネントに追加しますが、SpringLayout.Constraintsを直接使う代わりにputConstraint()を使っています。
リスト4 putConstraint()を使って2番目のコンポーネントを追加する
Component left = ...;
Component right = ...;
SpringLayout layout = new SpringLayout();
JPanel panel = new JPanel(layout);
panel.add(left);
panel.add(right);
layout.putConstraint(SpringLayout.WEST, left, 5, SpringLayout.WEST, panel);
layout.putConstraint(SpringLayout.NORTH, left, 25, SpringLayout.NORTH, panel);
layout.putConstraint(SpringLayout.NORTH, right, 25, SpringLayout.NORTH, panel);
layout.putConstraint(SpringLayout.WEST, right, 20, SpringLayout.EAST, left);
|
putConstraint()のString引数はSpringLayoutの4つの定数、EAST、WEST、NORTH、SOUTHです。putConstraint()を使うときには必ず未知のコンポーネント位置をまず規定し、それを何か計算できるもの、又は(画面の枠など)固定したものに接続します。
BeanBuilderでSpringLayoutを使いこなす
SpringLayoutを視覚化するために、SunではBeanBuilder(参考文献)と呼ぶツールを用意しています。このツールはむしろJavaBeansコンポーネントを使う時のためのものですが、SpringLayoutを簡単にいろいろ試すこともできるようになっています。このツールが起動時にどう見えるかを図1に示します。
図1 BeanBuilderの起動画面
このツールの具体的なことについては取り上げませんが、一点だけ、BeanBuilderを使うことでコンポーネントをSpringLayoutで接続できるようになるのです。各コンポーネントのエッジ周辺には東西南北それぞれに4つの箱があります。一つの箱から矢印をドラッグし、どれか別の箱につなぐことができるのです。このツールがもうちょっと賢ければ、ギャップのサイズまで規定できるところなのですが、図2では開発途中で画面がどんな風に見えるかを示しています。
図2 BeanBuilderの使用画面
図2で分かる通り、矢印を特定のputConstraint()コールに視覚的に接続できるのです。
リスト5にあるのはSpringLayoutの使い方をお見せするために、ここでの説明に挙げた諸々をputConstraint()を使って接続するSpringFormTestプログラムです。(このコードをダウンロードできます。参考文献を見てください)
リスト5 完全なSpringLayoutの例
import java.awt.*;
import javax.swing.*;
public class SpringFormTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Spring Form");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
SpringLayout layout = new SpringLayout();
contentPane.setLayout(layout);
Component left = new JLabel("Left");
Component right = new JTextField(15);
contentPane.add(left);
contentPane.add(right);
layout.putConstraint(SpringLayout.WEST, left, 10,
SpringLayout.WEST, contentPane);
layout.putConstraint(SpringLayout.NORTH, left, 25,
SpringLayout.NORTH, contentPane);
layout.putConstraint(SpringLayout.NORTH, right, 25,
SpringLayout.NORTH, contentPane);
layout.putConstraint(SpringLayout.WEST, right, 20,
SpringLayout.EAST, left);
frame.setSize(300, 100);
frame.show();
}
}
|
図3はその結果を示します。
図3 SpringFormTestの画面
- この記事で使われているサンプル・コードをダウンロードして下さい。
-
Merlinの魔術 全ヒント集もお読み下さい。
-
BeanBuilderツールを使うと、コード無しにSpringLayoutをいろいろ試すことができます。 -
SpringLayoutクラスのJavadocを読んで下さい。 -
GridBagLayoutクラスのJavadocを読んで下さい。 - 「優れたGUIを構築する」(developerWorks , 2001年10月)をよく読んで下さい。Javaレイアウト・マネージャがいかにGUIデザインや設計プロセスを改善するかを学べるはずです。
- チュートリアル「Developing accessible GUIs with Swing 」(developerWorks 2002年12月)を読んでSection 508アクセシビリティ(身障者対応を促進するアメリカの法令)対応の設計についても勉強してください。
- Sunの
SpringLayouttutorialもぜひ読んでください。 - developerWorks のJava technology ゾーンには、Javaプログラミングのあらゆる側面に関する記事が豊富にあります。

John Zukowskiは、JZ Ventures, Inc.の戦略的Javaコンサルティングを推進し、数多くのjGuruのコミュニティー主導のJava FAQsで常任指導者として活躍しています。最新の著書には、Apressから出版された「 Java Collections」および「 Definitive Guide to Swing for Java 2」 (第2版) があります。彼のメール・アドレスはjaz@zukowski.net です。