🐡

Swingのレイアウトマネージャー<後編>[Java]

に公開

はじめに

こんにちは。
プログラミング初心者wakinozaと申します。
Java勉強中に調べたことを記事にまとめています。

十分気をつけて執筆していますが、なにぶん初心者が書いた記事なので、理解が浅い点などあるかと思います。
間違い等あれば、指摘いただけると助かります。

記事を参考にされる方は、初心者の記事であることを念頭において、お読みいただけると幸いです。

対象読者

  • Javaを勉強中の方
  • Swingのレイアウトマネージャーについて知りたい方

記事のテーマ

  • SwingでGUIアプリケーションを作った際に、コンポーネントの配置が思うようにならなくて苦労しました。Swingのレイアウトは種類が豊富なので、備忘録も兼ねてまとめることにしました

  • 記事は2部構成です

  • 前編ではSwingの歴史と概論についてまとめていきます

https://zenn.dev/wakinoza/articles/002cf392251830

  • 本記事(後編)では、Swing における具体的なレイアウトマネージャーをいくつか紹介します

動作環境

  • MacBook(Intel CPU 搭載)
  • Oracle Java 21
  • Intellij IDEA Community Edition 2025.1.2

目次

1. BorderLayout
2. FlowLayout
3. GridLayout
4. BoxLayout
5. CardLayout
6. GridBagLayout
7. SpringLayout

本文

1. BorderLayout

1-1.BorderLayoutの特徴

BorderLayoutは、コンポーネントを東西南北中央の5つの領域に配置します。

  • NORTH (北): コンテナの上部に配置されます
  • SOUTH (南): コンテナの下部に配置されます
  • EAST (東): コンテナの右側に配置されます
  • WEST (西): コンテナの左側に配置されます
  • CENTER (中央): コンテナの残りのスペースをすべて占有します

各領域に配置できるコンポーネントは一つだけです。
1つの領域に複数のコンポーネントを追加すると、最後に追加したコンポーネントだけが表示され、その前に追加されたものは表示されなくなります。
1つの領域に複数のコンポーネントを配置したい場合は、JPanelなどの中間コンテナを利用して、コンポーネントを入れ子構造にすることで実現できます。

1-2. BorderLayoutのコンストラクタ

BorderLayoutのコンストラクタは、2つのオーバーロードがあります。

説明
public BorderLayout() コンポーネント間に間隔を設けずに、新しいボーダー・レイアウトを構築します。
public BorderLayout(int hgap, int vgap) コンポーネント間に間隔を指定して、新しいボーダー・レイアウトを構築します。 第1引数のhgapで水平方向の間隔を、第2引数のvgapで垂直方向の間隔をピクセルで指定します。
JFrame frame = new JFrame("BorderLayoutの説明");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

// コンテナのレイアウトをBorderLayoutに設定
// 水平・垂直のギャップを5pxに設定
frame.setLayout(new BorderLayout(5, 5));

// 各領域にボタンを配置
frame.add(new JButton("NORTH"), BorderLayout.NORTH);
frame.add(new JButton("SOUTH"), BorderLayout.SOUTH);
frame.add(new JButton("EAST"), BorderLayout.EAST);
frame.add(new JButton("WEST"), BorderLayout.WEST);
frame.add(new JButton("CENTER"), BorderLayout.CENTER);

frame.setVisible(true);

1-3. BorderLayoutの向いている配置スタイル

ボーダーレイアウトは、メニューバーやサイドバー、ヘッダーやフッターなどウィンドウの固定の位置にコンポーネントを配置したい場合に便利です。
また、 CENTER はウインドウサイズに追随して拡大・縮小するため、可変サイズのコンテンツ(例:エディタ、表示パネル)を扱う用途に適します。

1-4. BorderLayoutのサイズ調整の法則

コンポーネントのサイズは、以下の基準で自動的に調整されます。

  1. NORTHとSOUTH : 高さは内部のコンポーネントの推奨サイズに合わせ、幅はコンテナの横幅いっぱいに広がります
  2. EASTとWEST : 幅は内部のコンポーネントの推奨サイズに合わせ、高さはNORTHとSOUTHの領域を除いたコンテナの高さいっぱいに広がります
  3. CENTER : NORTH・SOUTH・EAST・WESTのコンポーネントが配置された後の、残りのすべての領域を占有します

このような法則があるため、特にCENTER領域は、内部コンポーネントの推奨サイズは無視される傾向があります。
CENTER領域は、ウインドウサイズに合わせて自動的にサイズ変更が求められるようなUIに適していると言えます。

2. FlowLayout

2-1. FlowLayoutの特徴

フローレイアウトは、コンポーネントを左から右へ、上から下へと、自然な流れで配置するシンプルなレイアウトマネージャーです。
コンポーネントは、コンテナの幅に収まる限り、水平方向に続けて配置され、コンテナの幅を超えると自動的に次の行に折り返されます。

左右どちらの方向にフローするかは、内部コンポーネントのComponentOrientationプロパティによって決まります。
java.awt.ComponentOrientationクラスは、コンポーネントやテキストの方向性(左→右、右→左など)を表現するクラスです。この方向性は、システムのロケール(地域や言語設定)に基づいて自動的に設定されます。
英語や日本語など文字を左から右へ書く言語を利用している場合はComponentOrientation.LEFT_TO_RIGHT(左から右へ)が、アラビア語やヘブライ語など文字を右から左へ書く言語を利用している場合は、ComponentOrientation.RIGHT_TO_LEFT(右から左へ)が自動的に設定されています。

setComponentOrientationメソッドを呼び出すことで、変更することも可能ですが、特殊なケース(例:日本語環境で部分的にアラビア語のUIを表示したい場合)を除いて、手動で設定する必要はほとんどありません。

英語や日本語環境で開発している場合は、フローレイアウトは基本的に左から右へ配置されると覚えておきましょう。

2-2. FlowLayoutのコンストラクタ

FlowLayoutのコンストラクタは、3つのオーバーロードがあります。

説明
public FlowLayout() 新しいFlowLayoutを構築します。引数がない場合は、配置はデフォルトの「中央揃え」、間隔は水平方向・垂直方向ともにデフォルトの5pxとなります
public FlowLayout(int align) 引数で指定された配置方法で、新しいFlowLayoutを構築します。間隔は水平方向・垂直方向ともにデフォルトの5pxとなります
public FlowLayout(int align, int hgap, int vgap) 第1引数で指定された配置方法で、新しいFlowLayoutを構築します。 第2引数のhgapで水平方向の間隔を、第3引数のvgapで垂直方向の間隔をピクセル単位で指定します。

引数のalignは、内部コンポーネントの配置方法を指定します。
指定する際は、定数を利用します。

  • FlowLayout.CENTER:中央揃え(デフォルト)
  • FlowLayout.LEFT:左揃え
  • FlowLayout.RIGHT:右揃え
  • FlowLayout.LEADING:文頭揃え。日本語などの左から右へ書く言語の場合はFlowLayout.LEFTとなる。
  • FlowLayout.TRAILING:文末揃え。日本語などの左から右へ書く言語の場合はFlowLayout.RIGHTとなる。
JFrame frame = new JFrame("FlowLayoutの説明");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

// コンテナのレイアウトをFlowLayoutに設定
// 配置は左揃え、水平・垂直のギャップを10pxに設定
frame.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));

frame.add(new JButton("Button 1"));
frame.add(new JButton("Button 2"));
frame.add(new JButton("Button 3"));
frame.add(new JButton("Button 4"));
frame.add(new JButton("Button 5"));
frame.add(new JButton("Button 6"));
frame.add(new JButton("Button 7"));
frame.add(new JButton("Button 8"));

frame.setVisible(true);

上のコードでウィンドウを横長にすると、ボタンは1列に並びます

ウィンドウの幅を縮めると、列は自動的に折り返されます。

2-3. FlowLayoutの向いている配置スタイル

アイコンやボタンなど複数のコンポーネントを横一列に並べるような、シンプルなUIに適しています。

2-4. FlowLayoutのサイズ調整の法則

FlowLayoutは内部コンポーネントのサイズを自動調整しないため、内部コンポーネントは推奨サイズで表示されます。

3. GridLayout

3-1. GridLayoutの特徴

グリッドレイアウトは、コンテナの利用できる領域を決まった行数と列数のグリッド(格子)状に区分けし、区分けしたセルにコンポーネントを配置するレイアウトマネージャーです。この時、格納されるコンポーネントは全て、セルと同じサイズに調整されます。
コンポーネントは、左右どちらから配置されるかは、コンテナのComponentOrientationプロパティによって決まります。日本語や英語など文字を左から右へ書く言語の環境下では、コンポーネントは左から右に配置され、行が埋まると、1つ下の行に続くという形で配置されます。

3-2. GridLayoutのコンストラクタ

GridLayoutのコンストラクタは、3つのオーバーロードがあります。

説明
public GridLayout() 1行×1列の新しいGridLayoutを構築します
public GridLayout(int rows, int cols) 第1引数のrowsで行数を、第2引数のcolsで列数を指定し、新しいGridLayoutを構築します
public GridLayout(int rows, int cols, int hgap, int vgap) 第1引数のrowsで行数を、第2引数のcolsで列数を指定し、新しいGridLayoutを構築します。 第3引数のhgapで水平方向の間隔を、第4引数のvgapで垂直方向の間隔をピクセル単位で指定します
JFrame frame = new JFrame("GridLayoutの説明");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

// 3行3列で間隔が5ピクセルずつのGridLayoutを設定
frame.setLayout(new GridLayout(3, 3, 5, 5));

// 9つのボタンを追加
for (int i = 1; i <= 9; i++) {
  frame.add(new JButton("Button " + i));
}

frame.setVisible(true);

3-3. GridLayoutの向いている配置スタイル

電卓のボタンやカレンダー、マス目など、同じサイズの要素を均一に配置したい場合に適しています。

3-4. GridLayoutのサイズ調整の法則

内部コンポーネントは、グリッドのセルいっぱいに広がるようにサイズが調整されます。そのため、内部コンポーネントの推奨サイズは無視される傾向にあります。

4. BoxLayout

4-1. BoxLayoutの特徴

ボックスレイアウトは、コンポーネントを縦または横方向に並べて配置するレイアウトマネージャーです。
フローレイアウトと似ていますが、以下の点で異なります。

  • 内部コンポーネントを縦方向に並べることができる
  • コンポーネントのサイズが自動的に調整される
  • コンポーネント間の間隔を柔軟に調整できる

4-2. BoxLayoutのコンストラクタ

説明
public BoxLayout(Container target, int axis) 第1引数で指定したコンポーネントを、第2引数で指定した方向に並べるBoxLayoutを構築します

引数axisは、定数を格納することが推奨されています。

  • BoxLayout.X_AXIS:横方向(左から右へ)にコンポーネントを配置します
  • BoxLayout.Y_AXIS:縦方向(上から下へ)にコンポーネントを配置します
  • BoxLayout.LINE_AXIS:文字を書く方向にコンポーネントを配置します
  • BoxLayout.PAGE_AXIS:複数のページにまたがって行が進んでいく方向にコンポーネントを配置します

下2つの定数は、コンテナの ComponentOrientationプロパティで方向が決定します。
日本語や英語環境の場合は、BoxLayout.LINE_AXISは「横方向(左から右へ)」、BoxLayout.PAGE_AXISは「縦方向(上から下へ)」の方向に配置します。

JFrame frame = new JFrame("BoxLayoutの説明1");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

//ボタンを格納するJPanel
JPanel buttonPanel = new JPanel();
// ボタンパネルにBoxLayoutをセット(垂直方向)
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));

buttonPanel.add(new JButton("Button 1"));
buttonPanel.add(new JButton("Button 2"));
buttonPanel.add(new JButton("Button 3"));

//ボタンパネルをframeに追加する
frame.add(buttonPanel, BorderLayout.CENTER);

frame.setVisible(true);

4-3. BoxLayoutの向いている配置スタイル

アイコンやボタンなどを、横一列や縦一列に並べる場合に便利です。

また、ボックスレイアウトには「透明なコンポーネント」を配置し、コンポーネントの間隔を緻密に調整する仕組みが用意されています。そのため、入れ子状態のコンテナにボックスレイアウトを設定することで、複雑なUIも作成することができます。
「透明なコンポーネント」については後ほど説明します。

4-4. BoxLayoutのサイズ調整の法則

ボックスレイアウトの内部コンポーネントのサイズは、コンポーネントの推奨サイズや最大サイズ、コンテナのサイズに合わせて自動的に調節されます。

  • 水平方向に並べている場合 (BoxLayout.X_AXIS):
    高さ: コンポーネントの最大サイズの高さに合わせて揃えられます。
    幅: コンポーネントの推奨サイズの幅が尊重されますが、コンテナの幅が足りない場合は縮小し、逆に余っている場合は最大サイズの幅まで拡大される可能性があります。

  • 垂直方向に並べている場合 (BoxLayout.Y_AXIS):
    幅: コンポーネントの最大サイズの幅に合わせて揃えられます。
    高さ: コンポーネントの推奨サイズの高さが尊重されますが、コンテナの高さが足りない場合は縮小し、逆に余っている場合は最大サイズの高さまで拡大される可能性があります。

コンポーネントの推奨サイズを指定したい場合は、JComponentクラスのPreferredSizeメソッドを、コンポーネントの最大サイズを指定したい場合は、JComponentクラスのsetMaximumSizeメソッドを呼び出すことで実現できます。

説明
public void setPreferredSize(Dimension preferredSize) このコンポーネントの推奨サイズを指定した値に設定します
public void setMaximumSize(Dimension maximumSize) このコンポーネントの最大サイズを指定した値に設定します

4-5. BoxLayoutの配置調整

ボックスレイアウトで、コンポーネントを特定の方向に揃えたい場合は、JComponentクラスのsetAlignmentXメソッドとsetAlignmentYメソッドを呼び出すことで、実現できます。

水平方向に並べている場合 (BoxLayout.X_AXIS):

  • コンポーネントは水平に並べられます。
  • setAlignmentYメソッドを使用して、垂直方向の整列(上揃え、中央揃え、下揃え)を制御します。
  • 例えば、コンポーネントを上に揃えたい場合は、setAlignmentY(Component.TOP_ALIGNMENT)を使用します。
定数 説明
Component.TOP_ALIGNMENT 上揃え
Component.CENTER_ALIGNMENT 中央揃え
Component.BOTTOM_ALIGNMENT 下揃え

垂直方向に並べている場合 (BoxLayout.Y_AXIS):

  • コンポーネントは垂直に並べられます。
  • setAlignmentXメソッドを使用して、水平方向の整列(左揃え、中央揃え、右揃え)を制御します。
  • 例えば、コンポーネントを左に揃えたい場合は、setAlignmentX(Component.LEFT_ALIGNMENT)を使用します。
定数 説明
Component.LEFT_ALIGNMENT 左揃え
Component.CENTER_ALIGNMENT 中央揃え
Component.RIGHT_ALIGNMENT 右揃え

4-6. BoxLayoutの間隔調整

フローレイアウトやグリッドレイアウトでは、コンポーネント同士の間隔は、コンストラクタで一括指定していました。

ボックスレイアウトでは、コンポーネントと「透明なコンポーネント」を交互に並べていくという考え方で間隔を制御します。
透明なコンポーネントには主に 3 種類があります。
これらは Boxクラスのメソッドで生成でき、それぞれ用途に応じて間隔を柔軟に調整できます。

4-6-1. Strut

Strutとは、固定幅の隙間です。ウィンドウサイズが変更されてもこの隙間のサイズは変更されません。

メソッド 説明
Box.createHorizontalStrut(int width) 水平方向の固定スペース
Box.createVerticalStrut(int height) 垂直方向の固定スペース
4-6-2. Glue

Glueとは、可変長の隙間です。ウィンドウサイズを変更すると、このスペースが拡大・縮小します。

メソッド 説明
Box.createHorizontalGlue() 水平方向の柔軟なスペース
Box.createVerticalGlue() 垂直方向の柔軟なスペース
4-6-3. RigidArea

RigidAreaは、固定された四角形の領域です。
特定の場所に決まったサイズの空きスペースを確保したい場合に使用します。

メソッド 説明
Box.createRigidArea(Dimension d) 固定の領域

以下に、アライメントと透明なコンポーネントを併用したコード例を示します。

JFrame frame = new JFrame("BoxLayoutの説明2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);


JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));

JButton button1 = new JButton("Left");
// ボタン1の垂直方向のアライメントを上揃えに設定
button1.setAlignmentY(Component.TOP_ALIGNMENT);
buttonPanel.add(button1);

// ボタンとボタンの間に固定の隙間 (Strut) を追加
buttonPanel.add(Box.createHorizontalStrut(20));

JButton button2 = new JButton("Center");
// ボタン2の垂直方向のアライメントを中央揃えに設定
button2.setAlignmentY(Component.CENTER_ALIGNMENT);
buttonPanel.add(button2);

// 残りのスペースを全て吸収する接着剤 (Glue) を追加
buttonPanel.add(Box.createHorizontalGlue());

JButton button3 = new JButton("Right");
button3.setPreferredSize(new Dimension(100, 80));
// ボタン3の垂直方向のアライメントを下揃えに設定
button3.setAlignmentY(Component.BOTTOM_ALIGNMENT);
buttonPanel.add(button3);

frame.add(buttonPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

5. CardLayout

5-1. CardLayoutの特徴

複数のコンポーネントを重ねて配置し、そのうち一つを選んで表示できるレイアウトマネージャーです。
紙芝居のように、複数の画面を重ねて配置し、一番前の画面だけが見える状態です。

各コンポーネントに名前(String)を付けて管理します。
この名前を使って、表示するコンポーネントを切り替えます。

5-2. CardLayoutのコンストラクタ

CardLayoutのコンストラクタは、2つのオーバーロードがあります。

説明
public CardLayout() 新しいCardLayoutを構築します
public CardLayout(int hgap, int vgap) 引数で指定された間隔をあけた新しいCardLayoutを構築します。第1引数のhgapで水平方向の間隔を、第2引数のvgapで垂直方向の間隔を表します

カードレイアウトは、1つのレイアウトに1つのコンポーネントしか表示できません。
そのため、引数2つのコンストラクタで指定されている「間隔」とは、コンポーネント間の間隔ではなく、レイアウトを設定したコンテナと各カードとの間の間隔のことを指します。

また、カードレイアウトにコンポーネントを追加する際に重要なのは、カードに「名前」をつけることです。
カードの切り替えは、「名前」を利用して行います。
そのため、「名前」がないと、カードを表示することができません。

「名前」は、addメソッドの引数で指定します。

説明
public void add(Component comp, Object constraints) 第1引数に配置したいコンポーネントを指定し、第2引数にそのコンポーネントのカードにつける名前を指定します

同じカードレイアウト内では、カード名は重複してはいけません。

また、指定したカードを表示するには、次のメソッドを使います。

説明
public void show(Container parent, String name) 第1引数にカードレイアウトを指定したコンテナを指定し、第2引数にカードの名前を指定しすることで、指定されたカードを表示します
JFrame frame = new JFrame("CardLayoutの説明");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

// CardLayoutのインスタンスを作成
CardLayout cardLayout = new CardLayout();

JPanel cardPanel = new JPanel();
cardPanel.setLayout(cardLayout);

// ボタン1
JButton button1 = new JButton("Card 1: First Button");
cardPanel.add(button1, "firstCard"); // addメソッドで名前を指定

// ボタン2
JButton button2 = new JButton("Card 2: Second Button");
cardPanel.add(button2, "secondCard"); // addメソッドで名前を指定

// ボタン3
JButton button3 = new JButton("Card 3: Third Button");
cardPanel.add(button3, "thirdCard"); // addメソッドで名前を指定

// showメソッドで、指定した名前のカードを表示
cardLayout.show(cardPanel, "secondCard");

frame.add(cardPanel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);

5-3. CardLayoutの向いているスタイル

アプリケーションの動作状況に応じて、表示する画面を完全に切り替えたい場合などに適しています。

5-4. CardLayoutのサイズ調整の法則

各コンポーネントは、CardLayoutが設定された親コンテナのサイズいっぱいに広がります。
そのため、コンポーネントの推奨サイズは無視される傾向にあります。

6. GridBagLayout

6-1. GridBagLayoutの特徴

グリッドバッグレイアウトは、グリッドベースの配置を拡張し、セルまたは複数セルにまたがる配置を柔軟に制御できるレイアウトマネージャーです。
グリッドレイアウトと似ていますが、各セルのサイズや行や列のサイズを個別に調整できる点、複数のセルにまたがるコンポーネントを配置することができる点に特徴があります。

GridBagLayoutは精密なレイアウトを作成できるというメリットがありますが、各コンポーネントに個別設定が必要なため、構成が複雑になり、可読性が低下しやすいというデメリットもあります。

グリッドの全体の方向は、コンテナのComponentOrientationプロパティによって決まります。
日本語や英語など文字を左から右へ書く言語の環境下では、グリッドの座標(0, 0)はコンテナの左上隅になります。この場合、X座標は右方向に、Y座標は下方向に値が増加します。

6-2. GridBagLayoutのコンストラクタ

説明
public GridBagLayout() 新しいGridBagLayoutを構築します。

あらかじめ配置条件を設定した後、addメソッドでコンポーネントを追加します。
各コンポーネントの配置とサイズは、java.awt.GridBagConstraintsクラスを使用して指定します。
GridBagConstraintsクラスには多数のフィールドが設けられており、これらのフィールドに値や定数を代入することで、各コンポーネントの配置やサイズを指定します。
代表的なフィールドは、以下の通りです。

フィールド名 説明
public int gridx コンポーネントを配置するセルの座標の列
public int gridy コンポーネントを配置するセルの座標の行
public int gridwidth 占有するセルの数
public int gridheight 占有するセルの数
public double weightx 水平方向にウィンドウのサイズが変更されたときに、余分なスペースをどのくらいの割合で分配するかを指定します。0.0から1.0までの値を指定できます(値が0.0のときは余分なスペースが割り当てられず、値が大きいほどより多くのスペースが割り当てられる)
public double weighty 垂直方向にウィンドウのサイズが変更されたときに、余分なスペースをどのくらいの割合で分配するかを指定します。0.0から1.0までの値を指定できます(値が0.0のときは余分なスペースが分配されず、値が大きいほどより多くのスペースが割り当てられる)
public int anchor コンポーネントをセル内でどの位置に配置するかを定数で指定します
public int fill コンポーネントが割り当てられたスペース内でどのように拡大するかを定数で指定します
public Insets insets コンポーネントの周りの余白(パディング)を指定します

コード例で見てみましょう。

JFrame frame = new JFrame("GridBagLayoutの説明");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

// JPanelを作成し、GridBagLayoutを設定
JPanel panel = new JPanel(new GridBagLayout());

// GridBagConstraintsオブジェクトを作成
GridBagConstraints gbc = new GridBagConstraints();

// 余白を設定
gbc.insets = new Insets(5, 5, 5, 5);

// ボタンA
JButton buttonA = new JButton("Button A");
gbc.gridx = 0; // 0列目
gbc.gridy = 0; // 0行目
gbc.weightx = 1.0; // 水平方向に余白を割り当てる
gbc.fill = GridBagConstraints.NONE; // 拡大しない
panel.add(buttonA, gbc);

// ボタンB
JButton buttonB = new JButton("Button B");
gbc.gridx = 1; // 1列目
gbc.gridy = 0; // 0行目
gbc.weighty = 1.0; // 垂直方向に余白を割り当てる
gbc.fill = GridBagConstraints.VERTICAL; // 垂直方向に拡大
panel.add(buttonB, gbc);

// ボタンC(2つの列にまたがって配置する)
JButton buttonC = new JButton("Button C");
gbc.gridx = 0; // 0列目
gbc.gridy = 1; // 1行目
gbc.gridwidth = 2; // 2つの列にまたがる
gbc.weightx = 1.0; // 水平方向に余白を割り当てる
gbc.fill = GridBagConstraints.HORIZONTAL; // 水平方向に拡大
panel.add(buttonC, gbc);

frame.add(panel);
frame.setVisible(true);

6-3. GridBagLayoutの向いているスタイル

ウィンドウのサイズ変更に応じて、特定のコンポーネントを拡大・縮小させたい場合や、複雑で精密なレイアウトを作成したい場合に向いています。

7. SpringLayout

7-1. SpringLayoutの特徴

スプリングレイアウトは、コンポーネントをコンテナ内の絶対座標で配置するのではなく、コンポーネントの辺(上、下、左、右)やサイズを、他のコンポーネントの辺やコンテナの辺との相対的な関係で定義します。
この関係は Springインスタンスで表現します。
Spring はコンポーネント間を“バネ”のように結び、ウィンドウサイズの変化に応じてレイアウトを動的に調整します。

ウィンドウサイズに合わせて動的な配置が可能になる一方、コードが煩雑になるデメリットがあります。Springインスタンスは2つのコンポーネント間の制約であるため、複数のコンポーネントがそれぞれ別の制約を設定していると、総合するとどのような配置になるのか直感的に理解しにくくなったり、想定外の配置になった際にデバッグが困難になるという欠点もあります。

7-2. SpringLayoutのコンストラクタ

説明
public SpringLayout() 新しいSpringLayoutを構築します

各コンポーネントに対して制約を設定するにはSpringLayoutクラスで用意されているputConstraintメソッドを使います。

説明
public void putConstraint(String e1, Component c1, int pad, String e2, Component c2) コンポーネントc1のエッジ e1をコンポーネントc2のエッジe2にリンクします

制約を設定したいコンポーネントを、第2引数のc1で指定します。このコンポーネントのどの部分に対して制約を設定をするのかは、以下の定数で第1引数e1に指定します。

定数 説明
SpringLayout.NORTH 上端
SpringLayout.SOUTH 下端
SpringLayout.WEST 左端
SpringLayout.EAST 右端

制約の基準となるコンポーネントは第5引数のc2に、基準コンポーネントのどの部分に制約を課すのかは、同じく定数で第4引数のe2に指定します。
そして、基準となるコンポーネントの部分から設定したいコンポーネントの部分までの距離を設定するのが第3引数のpadです。

JFrame frame = new JFrame("SpringLayoutの説明");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);

// JPanelを作成し、SpringLayoutを設定
JPanel panel = new JPanel();
SpringLayout layout = new SpringLayout();
panel.setLayout(layout);

// ボタンA
JButton buttonA = new JButton("Button A");
panel.add(buttonA);

// ボタンB
JButton buttonB = new JButton("Button B");
panel.add(buttonB);

// ボタンC
JButton buttonC = new JButton("Button C");
panel.add(buttonC);

// ボタンAの制約を設定
// パネルの左端から5ピクセル、上端から5ピクセル離す
layout.putConstraint(SpringLayout.WEST, buttonA, 5, SpringLayout.WEST, panel);
layout.putConstraint(SpringLayout.NORTH, buttonA, 5, SpringLayout.NORTH, panel);

// ボタンBの制約を設定
// ボタンAの右端から5ピクセル、上端はボタンAと揃える
layout.putConstraint(SpringLayout.WEST, buttonB, 5, SpringLayout.EAST, buttonA);
layout.putConstraint(SpringLayout.NORTH, buttonB, 0, SpringLayout.NORTH, buttonA);

// ボタンCの制約を設定
// ボタンAの下端から5ピクセル、左端はボタンAと揃える
layout.putConstraint(SpringLayout.NORTH, buttonC, 5, SpringLayout.SOUTH, buttonA);
layout.putConstraint(SpringLayout.WEST, buttonC, 0, SpringLayout.WEST, buttonA);

// パネルのサイズをボタンの配置に合わせて調整
layout.putConstraint(SpringLayout.EAST, panel, 5, SpringLayout.EAST, buttonB);
layout.putConstraint(SpringLayout.SOUTH, panel, 5, SpringLayout.SOUTH, buttonC);

// フレームにパネルを追加
frame.add(panel);
frame.setVisible(true);

上のコードを実行すると、以下のようになります。ウィンドウのサイズを変えても、3つのボタンは同じ間隔を開けたまま、左上に留まります。

7-3. SpringLayoutの向いているスタイル

ウィンドウサイズに合わせて、動的に変化させたいUIを作成する場合に向いています。
また、ウィンドウサイズがどのように変化しても、指定のコンポーネントを指定の場所(例えば常に左上)にとどめたい場合に有用です。

7-4. SpringLayoutのサイズ調整の法則

スプリングレイアウトでは、各コンポーネントはSpringの制約に基づきサイズが決定します。そのため、各コンポーネントの元々の推奨サイズは無視される傾向にあります。

まとめ

  • BorderLayout: 画面を東西南北中央の5つの領域に分割し、固定されたヘッダーやサイドバーの配置に適しています。

  • FlowLayout: コンポーネントを左から右へ、順に配置するシンプルなレイアウト。ツールバーやボタンの並びに便利です。

  • GridLayout: コンポーネントを均等なサイズのグリッドに配置し、電卓のような均一なUIの作成に向いています。

  • BoxLayout: コンポーネントを縦または横に一列に並べることができ、コンポーネント間のスペースを柔軟に調整する機能が特徴です。

  • CardLayout: 複数のコンポーネントを重ねて配置し、必要なときに表示する画面を切り替える特殊なレイアウトです。

  • GridBagLayout: グリッドをベースに、各セルのサイズや配置を細かく制御できるため、精密なレイアウト作成に適しています。

  • SpringLayout: コンポーネント間の相対的な関係に基づいて配置を定義する、柔軟性の高いレイアウトです。


記事は以上です。
最後までお読みいただき、ありがとうございました。

参考情報一覧

この記事は以下の情報を参考にして執筆しました。

GitHubで編集を提案

Discussion