レイアウトマネージャ、作れますか?
ある程度、複雑なレイアウトになると、やはりレイアウトマネージャを自分で作るのが最も簡単な解決法となってくるでしょう。レイアウトマネージャは、LayoutManagerまたはLayoutManager2インターフェイスをimplementsして作成します。LayoutManagerがレイアウトマネージャの基本となるもので、LayoutManager2はそれをさらに拡張したものです。
レイアウトマネージャというのは、AWT/Swingを使っているなら常にお世話になっているものですが、意外に自分で作る人は少ないようです。既に出来合いのものがいくつも用意されていますから、自分で作成するとなると「面倒くさい」と感じてしまうのでしょう。が、それほど難しいものではありませんので、一度自作に挑戦してみましょう。SwingのみならずAWTでも利用できるものですから、一度作れば幅広く活用できます。
package jp.codezine; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; public class SampleApp extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; public SampleApp(){ this.setSize(new Dimension(300,200)); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setLayout(new MyLayout()); actionPerformed(null); } public void actionPerformed(ActionEvent e){ JButton btn = new JButton("button"); btn.setFont(new Font("Serif",Font.PLAIN,18)); btn.addActionListener(this); this.add("",btn); } public static void main(String[] args) { new SampleApp().setVisible(true); } } class MyLayout implements LayoutManager { private Container container; private ArrayList<Component> components; private int miniW = 50; private int miniH = 20; public MyLayout(){ components = new ArrayList<Component>(); } @Override public void addLayoutComponent(String name, Component comp) { components.add(comp); if (container != null) container.doLayout(); } @Override public void removeLayoutComponent(Component comp) { components.remove(comp); if (container != null) container.doLayout(); } @Override public void layoutContainer(Container parent) { container = parent; int insetSize = 20; int w = (parent.getWidth() - insetSize * 2) / 2; int h = (parent.getHeight() - insetSize * 2); int size = components.size() == 0 ? 1 : components.size(); int insetW = w / size; int insetH = h / size; int x = insetSize; int y = insetSize; for(Component c: components){ c.setBounds(new Rectangle(x,y,w,insetH)); x += insetW; y += insetH; } } @Override public Dimension minimumLayoutSize(Container parent) { return new Dimension(100,100); } @Override public Dimension preferredLayoutSize(Container parent) { return parent.getPreferredSize(); } }

例として、先ほどの簡易レイアウトをMyLayoutというレイアウトマネージャ・クラスを定義して利用する形に修正してみました。LayoutManagerインターフェイスは、以下の5つのメソッドが定義されています。
- public void addLayoutComponent(String name, Component comp)
- public void removeLayoutComponent(Component comp)
- public void layoutContainer(Container parent)
- public Dimension minimumLayoutSize(Container parent)
- public Dimension preferredLayoutSize(Container parent)
String値と、組み込んだComponentが渡されます。Componentが渡されます。Containerは自身に組み込まれているLayoutManagerのlayoutContainerを呼び出して再レイアウトを行います。引数には、再レイアウトするContainerが渡されます。Dimensionで返します。Dimensionで返します。 最大のポイントは、layoutContainerでしょう。ここでのレイアウト処理さえできれば、後はそれほど難しくはありません。
