概要

TitledBorderのタイトル文字列を縦(左側)に表示します。

サンプルコード

class VerticalTitledBorder extends TitledBorder {
  private final JLabel label;
  public VerticalTitledBorder(String title) {
    super(title);
    this.label = new JLabel(title);
    this.label.setOpaque(true);
    // this.label.putClientProperty(BasicHTML.propertyKey, null);
  }

  @Override public void paintBorder(
      Component c, Graphics g, int x, int y, int width, int height) {
    Border border = getBorder();
    String title = getTitle();
    if ((title != null) && !title.isEmpty() && border != null) {
      int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
      JLabel label = getLabel(c);
      Dimension size = label.getPreferredSize();
      Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0));

      int borderX = x + edge;
      int borderY = y + edge;
      int borderW = width - edge - edge;
      int borderH = height - edge - edge;

      int labelH = size.height;
      int labelW = height - insets.top - insets.bottom; // TEST: - (edge * 8);
      if (labelW > size.width) {
        labelW = size.width;
      }

      int ileft = edge + insets.left / 2 - labelH / 2;
      if (ileft < edge) {
        borderX -= ileft;
        borderW += ileft;
      }
      border.paintBorder(c, g, borderX, borderY, borderW, borderH);

      Graphics2D g2 = (Graphics2D) g.create();
      g2.translate(0, (height + labelW) / 2);
      g2.rotate(Math.toRadians(-90));
      // or: g2.transform(AffineTransform.getQuadrantRotateInstance(-1));
      label.setSize(labelW, labelH);
      label.paint(g2);
      g2.dispose();
    } else {
      super.paintBorder(c, g, x, y, width, height);
    }
  }

  @Override public Insets getBorderInsets(Component c, Insets insets) {
    Border border = getBorder();
    insets = getBorderInsets(border, c, insets);
    String title = getTitle();
    if ((title != null) && !title.isEmpty()) {
      int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
      JLabel label = getLabel(c);
      Dimension size = label.getPreferredSize();
      if (insets.left < size.height) {
        insets.left = size.height - edge;
      }
      insets.top += edge + TEXT_SPACING;
      insets.left += edge + TEXT_SPACING;
      insets.right += edge + TEXT_SPACING;
      insets.bottom += edge + TEXT_SPACING;
    }
    return insets;
  }

  // Copied from TitledBorder
  private Color getColor(Component c) {
    Color color = getTitleColor();
    if (color != null) {
      return color;
    }
    color = UIManager.getColor("TitledBorder.titleColor");
    if (color != null) {
      return color;
    }
    return (c != null) ? c.getForeground() : null;
  }

  private JLabel getLabel(Component c) {
    this.label.setText(getTitle());
    this.label.setFont(getFont(c));
    this.label.setForeground(getColor(c));
    this.label.setComponentOrientation(c.getComponentOrientation());
    this.label.setEnabled(c.isEnabled());
    this.label.setBackground(c.getBackground()); // ???
    return this.label;
  }

  private static Insets getBorderInsets(
      Border border, Component c, Insets insets) {
    if (border == null) {
      insets.set(0, 0, 0, 0);
    } else if (border instanceof AbstractBorder) {
      AbstractBorder ab = (AbstractBorder) border;
      insets = ab.getBorderInsets(c, insets);
    } else {
      Insets i = border.getBorderInsets(c);
      insets.set(i.top, i.left, i.bottom, i.right);
    }
    return insets;
  }
}
View in GitHub: Java, Kotlin

解説

    • TitledBorderのデフォルト(上)
    • Java 7から文字列がBorderの幅より長い場合...で省略されるようになった
    • TitledBorder#paintBorder(...)などをオーバーライドしてタイトルを左側中央に縦表示
    • TitledBorderVerticalTitledBorderの組み合わせ

参考リンク

コメント