• category: swing folder: MenuWithShadow title: Menuに半透明の影を付ける tags: [JMenu, JPopupMenu, UIManager, Border, Robot, Translucent] author: aterai pubdate: 2006-10-23T14:11:21+09:00 description: JMenuから開くJPopupMenuにBorderを設定して半透明の影を付けます。 image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTPz0ZEG6I/AAAAAAAAAek/pd0ErBB9eBg/s800/MenuWithShadow.png

概要

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では、ポップアップメニューがフレームの中にあるか外にあるかで、影のつけ方を切り替えています。外にある場合は、Robotを使って画面をキャプチャーしています。

メニューがフレームの外にはみ出す場合に、メニューをすばやく切り替えたりすると、ゴミが残ることがあるようです。参考リンクのcontrib.com.jgoodies.looks.common.ShadowPopupFactoryを使っても同様のゴミが出る場合があります。 再現しなくなった?ようです。


contrib.com.jgoodies.looks.common.ShadowPopupFactoryを使用しても、同様の影を作成することができます。JGoodies | We make Java look good and work wellなどからダウンロードして、以下のように設定してみてください。

//UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
contrib.com.jgoodies.looks.common.ShadowPopupFactory.install();

Web Startで起動してフレームの外側にメニューが表示される場合は、java.security.AccessControlException: access denied (java.awt.AWTPermission createRobot)が発生します。

参考リンク

コメント