概要

JMenuから開くJPopupMenuBorderを設定して半透明の影を付けます。

サンプルコード

public class CustomPopupMenuUI extends BasicPopupMenuUI {
  public static ComponentUI createUI(JComponent c) {
    return new CustomPopupMenuUI();
  }

  private static boolean isHeavyWeightContainer(Component contents) {
    for (Container p = contents.getParent(); p != null; p = p.getParent()) {
      if ((p instanceof JWindow) || (p instanceof Panel)) {
        return true;
      }
    }
    return false;
  }

  public Popup getPopup(JPopupMenu popup, int x, int y) {
    Popup pp = super.getPopup(popup, x, y);
    JPanel panel = (JPanel) popup.getParent();
    if (isHeavyWeightContainer(panel)) {
      System.out.println("outer");
      Point p = new Point(x, y);
      panel.setBorder(new ShadowBorder(panel, p));
    } else {
      System.out.println("inner");
      panel.setBorder(new ShadowBorderInPanel());
    }
    panel.setOpaque(false);
    return pp;
  }
// ...
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、BasicPopupMenuUIを継承したCustomPopupMenuUIを作成してUIManagerで登録しています。

UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
  • このCustomPopupMenuUIではポップアップメニューの表示位置がフレームの内か外かで影のつけ方を切り替えている
    • 内側: ポップアップメニューに半透明のBorderを設定して影を描画
    • 外側: 別Windowでポップアップメニューが開くため、Robotを使って背景画面をキャプチャーし、その上に影を描画してBorderに設定

  • JGoodies | We make Java look good and work wellからJGoodiesダウンロードし、以下のようにcontrib.com.jgoodies.looks.common.ShadowPopupFactoryを使用して同様の影を表示する方法もある
    // UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
    contrib.com.jgoodies.looks.common.ShadowPopupFactory.install();
    

参考リンク

コメント