TITLE:Menuに半透明の影を付ける

Menuに半透明の影を付ける

編集者:Terai Atsuhiro~

作成日:2006-10-23
更新日:2021-10-16 (土) 00:34:28
  • 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を設定して半透明の影を付けます。

概要

メニューに半透明の影を付けます。

サンプルコード

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

#spandel
#screenshot
#spanend
  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;
  }

#spandel
**サンプルコード [#eb189a65]
#spanend
#spandel
#code{{
#spanend
 public class CustomPopupMenuUI extends BasicPopupMenuUI {
   public static ComponentUI createUI(JComponent c) {
     return new CustomPopupMenuUI();
   }
   private static int OFF = 4;
   private static float ALPHA = 0.12f;
   public static JFrame frame = null;
   private static boolean isInRootPanel(JComponent popup, Point p) {
     if(frame==null) return false;
     Rectangle r = frame.getBounds();
     Dimension d = popup.getPreferredSize();
     return r.contains(p.x, p.y, d.width+OFF, d.height+OFF);
   }
   public Popup getPopup(JPopupMenu popup, int x, int y) {
     Popup pp = super.getPopup(popup,x,y);
     JPanel panel = (JPanel)popup.getParent();
     Point p = new Point(x, y);
     if(isInRootPanel(panel, p)) {
       //System.out.println("inner");
       panel.setBorder(new ShadowBorderInPanel());
     }else{
       //System.out.println("outer");
       panel.setBorder(new ShadowBorder(panel,p));
     }
     panel.setOpaque(false);
     return pp;
   }
 ......
  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;
  }
#spanadd
// ...
#spanend
View in GitHub: Java, Kotlin
  • &jar;
  • &zip;

解説

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

解説

上記のサンプルでは、BasicPopupMenuUIを継承したCustomPopupMenuUIを作成してUIManagerで登録しています。
 CustomPopupMenuUI.frame = frame;
 UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
#spanadd
UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
#spanend
この CustomPopupMenuUI では、ポップアップメニューがフレームの中にあるか外にあるかで、影のつけ方を切り替えています。外にある場合は、Robot を使って画面をキャプチャしています。
  • このCustomPopupMenuUIではポップアップメニューの表示位置がフレームの内か外かで影のつけ方を切り替えている
    • 内側: ポップアップメニューに半透明のBorderを設定して影を描画
    • 外側: 別Windowでポップアップメニューが開くため、Robotを使って背景画面をキャプチャーし、その上に影を描画してBorderに設定
メニューがフレームの外にはみ出す場合に、メニューをすばやく切り替えたりすると、ゴミが残ることがあるようです。参考リンクのcontrib.com.jgoodies.looks.common.ShadowPopupFactory を使っても同様のゴミが出る場合があります。 substance のソースに添付されていた contrib.com.jgoodies.looks.common.ShadowPopupFactory も、src.zipに添付しています*1。テストする場合は、以下のように設定してみてください。
  • -
  • JGoodies | We make Java look good and work wellからJGoodiesダウンロードし、以下のようにcontrib.com.jgoodies.looks.common.ShadowPopupFactoryを使用して同様の影を表示する方法もある
     //CustomPopupMenuUI.frame = frame;
     //UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
     contrib.com.jgoodies.looks.common.ShadowPopupFactory.install();
    #spanadd
    // UIManager.put("PopupMenuUI","example.CustomPopupMenuUI");
    #spanend
    #spanadd
    contrib.com.jgoodies.looks.common.ShadowPopupFactory.install();
    #spanend
    

参考リンク

参考リンク

コメント

コメント