概要

JLabelの垂直位置を異なるパネル間でも揃えるため、最大幅のJLabelを検索してこれをすべての推奨サイズとして使用します。

サンプルコード

// @see javax/swing/plaf/metal/MetalFileChooserUI.java
class AlignedLabel extends JLabel {
  private static final int INDENT = 10;
  // private AlignedLabel[] group;
  protected List<AlignedLabel> group;
  protected int maxWidth;

  protected AlignedLabel(String text) {
    super(text);
    // setAlignmentX(JComponent.LEFT_ALIGNMENT);
    setHorizontalAlignment(SwingConstants.RIGHT);
  }

  @Override public Dimension getPreferredSize() {
    Dimension d = super.getPreferredSize();
    // Align the width with all other labels in group.
    return new Dimension(getMaxWidth() + INDENT, d.height);
  }

  private int getMaxWidth() {
    if (maxWidth == 0 && group != null) {
      int max = group.stream()
        .map(AlignedLabel::getSuperPreferredWidth)
        .reduce(0, Integer::max);
      group.forEach(al -> al.maxWidth = max);
    }
    return maxWidth;
  }

  private int getSuperPreferredWidth() {
    return super.getPreferredSize().width;
  }

  public static void groupLabels(List<AlignedLabel> group) {
    for (AlignedLabel al: group) {
      al.group = group;
    }
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、javax/swing/plaf/metal/MetalFileChooserUI.javaAlignedLabelを参考にして異なるパネル間でJLabelの垂直位置揃えを行っています。

  • AlignedLabel
    • JLabelを継承
    • JLabel#getPreferredSize()を垂直位置揃えを適用するラベルの中での最大幅を検索取得して返すようオーバーライド
  • BoxLayout
    • AlignedLabelとその右に配置するコンポーネントをBox.createHorizontalBox()で作成したBoxに追加
    • FileChooserHTTP ProxyのタイトルをTitledBorderで設定したBox2個作成し、上記のAlignedLabelを配置したBoxをそれぞれ追加
    • 複数のBoxAlignedLabelが配置されていても各AlignedLabelの推奨サイズの幅はすべて同じになっているため垂直位置は揃う

参考リンク

コメント