• category: swing folder: ToolBarButtonToolTipOrientation title: JToolBarの配置位置によってJToolTipの表示方向を切り替える tags: [JToolBar, JButton, JToolTip] author: aterai pubdate: 2024-01-15T04:11:11+09:00 description: JToolBarの配置位置、縦横の方向、言語依存の方向によってJToolTipの表示位置が常に内側になるよう切り替えます。 image: https://drive.google.com/uc?id=1u9OhK9Xb_egsfQ-hog8kHOP4gKoMon9Y

概要

JToolBarの配置位置、縦横の方向、言語依存の方向によってJToolTipの表示位置が常に内側になるよう切り替えます。

サンプルコード

private Component createToolBarButton(ColorItem item) {
  JButton button = new JButton(item.getIcon()) {
    private transient BalloonToolTip tip;
    private final JLabel label = new JLabel(" ", CENTER);

    @Override public Point getToolTipLocation(MouseEvent e) {
      String txt = getToolTipText();
      return Optional.ofNullable(txt).map(toolTipText -> {
        JToolTip tips = createToolTip();
        tips.setTipText(toolTipText);
        label.setText(toolTipText);
        Container bar = SwingUtilities.getAncestorOfClass(JToolBar.class, this);
        String constraint = calculateConstraint(bar.getParent(), bar);
        if (tips instanceof BalloonToolTip) {
          ((BalloonToolTip) tips).updateBalloonShape(constraint);
        }
        return getToolTipPoint(getPreferredSize(), tips.getPreferredSize(), constraint);
      }).orElse(null);
    }

    @Override public JToolTip createToolTip() {
      if (tip == null) {
        tip = new BalloonToolTip();
        LookAndFeel.installColorsAndFont(
            label, "ToolTip.background", "ToolTip.foreground", "ToolTip.font");
        tip.add(label);
        Container bar = SwingUtilities.getAncestorOfClass(JToolBar.class, this);
        String constraint = calculateConstraint(bar.getParent(), bar);
        tip.updateBalloonShape(constraint);
        tip.setComponent(this);
      }
      return tip;
    }

    @Override public void updateUI() {
      tip = null;
      super.updateUI();
    }
  };
  button.setOpaque(false);
  button.setToolTipText(item.getTitle());
  button.setFocusPainted(false);
  return button;
}

private static String calculateConstraint(Container source, Component toolBar) {
  String constraint = null;
  JToolBar bar = (JToolBar) toolBar;
  if (((BasicToolBarUI) bar.getUI()).isFloating()) {
    if (bar.getOrientation() == SwingConstants.VERTICAL) {
      boolean leftToRight = bar.getComponentOrientation().isLeftToRight();
      constraint = leftToRight ? BorderLayout.WEST : BorderLayout.EAST;
    }
  } else {
    LayoutManager lm = source.getLayout();
    if (lm instanceof BorderLayout) {
      constraint = (String) ((BorderLayout) lm).getConstraints(toolBar);
    }
  }
  return constraint == null ? BorderLayout.NORTH : constraint;
}

private static Point getToolTipPoint(Dimension btnSz, Dimension tipSz, String constraint) {
  double dx;
  double dy;
  switch (constraint) {
    case BorderLayout.WEST:
      dx = btnSz.getWidth();
      dy = (btnSz.getHeight() - tipSz.getHeight()) / 2d;
      break;
    case BorderLayout.EAST:
      dx = -tipSz.getWidth();
      dy = (btnSz.getHeight() - tipSz.getHeight()) / 2d;
      break;
    case BorderLayout.SOUTH:
      dx = (btnSz.getWidth() - tipSz.getWidth()) / 2d;
      dy = -tipSz.getHeight();
      break;
    default: // case BorderLayout.NORTH:
      dx = (btnSz.getWidth() - tipSz.getWidth()) / 2d;
      dy = btnSz.getHeight();
  }
  return new Point((int) (dx + .5), (int) (dy + .5));
}
View in GitHub: Java, Kotlin

解説

  • JToolBarBorderLayoutを設定したJPanel内に配置されている場合:
    • その配置位置(BorderLayout.NORTHBorderLayout.SOUTHBorderLayout.WESTBorderLayout.EAST)をBorderLayout#getConstraints(toolBar)メソッドで取得
    • JToolTipが親JPanel内に表示されるようJButton#getToolTipLocation(MouseEvent)をオーバーライドし、JPanel内配置位置に対応した表示位置となるようgetToolTipPoint(...)で計算
    • JToolTip表示のx軸座標はJButton相対で中央揃えになるよう計算するので、JToolBarに設定された言語依存の方向(ComponentOrientation)には影響されない
  • JToolBarがフロート状態(ツールバー専用のウィンドウにドラッグアウト)の場合:
    • ウィンドウが横長(BorderLayout.NORTHBorderLayout.SOUTHに配置された状態からドラッグアウト)の場合はJToolBarの言語依存の方向に依存せず、BorderLayout.NORTHに配置されていた場合と同様にその下側にJToolTipを表示
    • ウィンドウが縦長(BorderLayout.EASTBorderLayout.WESTに配置された状態からドラッグアウト)の場合
      • 言語依存の方向(JToolBar#getComponentOrientation())が左から右(ComponentOrientation.LEFT_TO_RIGHT)の場合はBorderLayout.WESTに配置されていた場合と同様にその右側にJToolTipを表示
      • 言語依存の方向(JToolBar#getComponentOrientation())が右から左(ComponentOrientation.RIGHT_TO_LEFT)の場合はBorderLayout.EASTに配置されていた場合と同様にその左側にJToolTipを表示

参考リンク

コメント