Swing/ScrollableWrapLayout の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/ScrollableWrapLayout へ行く。
- Swing/ScrollableWrapLayout の差分を削除
--- category: swing folder: ScrollableWrapLayout title: JPanelの子コンポーネントを水平方向で折り返す tags: [JPanel, FlowLayout, JScrollPane, LayoutManager] author: aterai pubdate: 2019-09-09T15:09:05+09:00 description: JPanelに配置した子コンポーネントを水平方向で折り返し、またそれらの水平間隔を動的に均等になるよう拡大します。 image: https://drive.google.com/uc?id=1Dnd-KMM4YnctkKvawDVGeCtPqD1fZfEO hreflang: href: https://java-swing-tips.blogspot.com/2019/10/wraps-jpanel-child-components.html lang: en --- * 概要 [#summary] `JPanel`に配置した子コンポーネントを水平方向で折り返し、またそれらの水平間隔を動的に均等になるよう拡大します。 #download(https://drive.google.com/uc?id=1Dnd-KMM4YnctkKvawDVGeCtPqD1fZfEO) * サンプルコード [#sourcecode] #code(link){{ class ScrollableWrapLayout extends FlowLayout { private final int fixedHorizontalGap; protected ScrollableWrapLayout(int align, int hgap, int vgap) { super(align, hgap, vgap); fixedHorizontalGap = hgap; } private int getPreferredHorizontalGap(Container target) { Insets insets = target.getInsets(); int columns = 0; int width = target.getWidth(); if (target.getParent() instanceof JViewport) { width = target.getParent().getBounds().width; } width -= insets.left + insets.right + fixedHorizontalGap * 2; for (int i = 0; i < target.getComponentCount(); i++) { Component m = target.getComponent(i); if (m.isVisible()) { Dimension d = m.getPreferredSize(); if (width - d.width - fixedHorizontalGap < 0) { columns = i; break; } width -= d.width + fixedHorizontalGap; } } return fixedHorizontalGap + width / columns; } @Override public void layoutContainer(Container target) { setHgap(getPreferredHorizontalGap(target)); super.layoutContainer(target); } @Override public Dimension preferredLayoutSize(Container target) { Dimension dim = super.preferredLayoutSize(target); synchronized (target.getTreeLock()) { if (target.getParent() instanceof JViewport) { dim.width = target.getParent().getBounds().width; for (int i = 0; i < target.getComponentCount(); i++) { Component m = target.getComponent(i); if (m.isVisible()) { Dimension d = m.getPreferredSize(); dim.height = Math.max(dim.height, d.height + m.getY()); } } } return dim; } } } }} * 解説 [#explanation] - 上: `JPanel + FlowLayout` - 上: `JPanel` + `FlowLayout` -- デフォルトの`JPanel`に`FlowLayout`を設定して`JScrollPane`に配置 -- 水平方向に`JPanel`が拡張されて水平`ScrollBar`が表示される - 下: `ScrollableWrapPanel + ScrollableWrapLayout` - 下: `ScrollableWrapPanel` + `ScrollableWrapLayout` -- `JPanel`に`Scrollable`を実装する`ScrollableWrapPanel`を作成し、これに`FlowLayout#preferredLayoutSize(...)`などをオーバーライドする`ScrollableWrapLayout`を設定して`JScrollPane`に配置 -- `ScrollableWrapPanel`の子コンポーネント間の水平間隔を親のリサイズに応じて動的・均等に拡大するよう`FlowLayout#layoutContainer(...)`メソッドをオーバーライド --- 最小値は初期水平間隔 --- 子コンポーネントはすべて同じ推奨サイズと想定 * 参考リンク [#reference] - [[JListのアイテムを範囲指定で選択>Swing/RubberBanding]] -- 子コンポーネントのレイアウト方法は`JList.HORIZONTAL_WRAP`を使用する場合と水平間隔以外はほぼ同じになる - [https://tips4java.wordpress.com/2008/11/06/wrap-layout/ Wrap Layout « Java Tips Weblog] * コメント [#comment] #comment #comment