• title: TitledBorderとMatteBorderを使用してTitledSeparatorを作成する tags: [JSeparator, TitledBorder, MatteBorder, JLabel, Icon, LinearGradientPaint] author: aterai pubdate: 2012-08-27T18:52:36+09:00 description: TitledBorderとMatteBorderを使用してTitle付きのSeparatorを作成します。

概要

TitledBorderMatteBorderを使用してTitle付きのSeparatorを作成します。

サンプルコード

class TitledSeparator extends JLabel {
  private final String title;
  private final Color target;
  private final int height;
  private final int titlePosition;
  public TitledSeparator(String title, int height, int titlePosition) {
    this(title, null, height, titlePosition);
  }
  public TitledSeparator(
      String title, Color target, int height, int titlePosition) {
    super();
    this.title = title;
    this.target = target;
    this.height = height;
    this.titlePosition = titlePosition;
    updateBorder();
  }
  private void updateBorder() {
    Icon icon = new TitledSeparatorIcon();
    setBorder(BorderFactory.createTitledBorder(
        BorderFactory.createMatteBorder(height, 0, 0, 0, icon), title,
        TitledBorder.DEFAULT_JUSTIFICATION, titlePosition));
  }
  @Override public Dimension getMaximumSize() {
    Dimension d = super.getPreferredSize();
    d.width = Short.MAX_VALUE;
    return d;
  }
  @Override public void updateUI() {
    super.updateUI();
    updateBorder();
  }
  private class TitledSeparatorIcon implements Icon {
    private int width = -1;
    private Paint painter1;
    private Paint painter2;
    @Override public void paintIcon(Component c, Graphics g, int x, int y) {
      int w = c.getWidth();
      Color color = getBackground();
      if (w != width || painter1 == null || painter2 == null) {
        width = w;
        Point2D start = new Point2D.Float(0f, 0f);
        Point2D end   = new Point2D.Float((float) width, 0f);
        float[] dist  = {0f, 1f};
        color = color == null ? UIManager.getColor("Panel.background") : color;
        Color tc = target == null ? color : target;
        painter1 = new LinearGradientPaint(
            start, end, dist, new Color[] {tc.darker(),   color});
        painter2 = new LinearGradientPaint(
            start, end, dist, new Color[] {tc.brighter(), color});
      }
      int h = getIconHeight() / 2;
      Graphics2D g2  = (Graphics2D) g.create();
      g2.setPaint(painter1);
      g2.fillRect(x, y,   width, getIconHeight());
      g2.setPaint(painter2);
      g2.fillRect(x, y + h, width, getIconHeight() - h);
      g2.dispose();
    }
    @Override public int getIconWidth() {
      return 200; //dummy width
    }
    @Override public int getIconHeight() {
      return height;
    }
  }
}
View in GitHub: Java, Kotlin

解説

TitledBorderと、左下右のInsets0(上余白のみ設定)でタイルアイコンでグラデーションを行うMatteBorderを組み合わせ、これを空のJLabelに設定することで、TitledSeparatorを作成しています。

    • タイトルの垂直位置をデフォルトのTitledBorder.DEFAULT_POSITIONにして、Separator上に重なるように表示
    • Java 1.6.0では、タイトルの上にSeparatorが表示される場合がある?(1.7.0では正常)
    • タイトルの垂直位置が上(TitledBorder.ABOVE_TOP)で、Separatorの上に表示
    • JSeparatorを使用

注: 縦のセパレータには未対応

参考リンク

コメント