• category: swing folder: TranslucentPopupMenu title: JPopupMenuを半透明にする tags: [JPopupMenu, JMenuItem, JWindow, Translucent] author: aterai pubdate: 2012-02-27T14:25:17+09:00 description: JPopupMenu自体の背景を透明に設定し、別途そのpaintComponent(...)メソッドをオーバーライドして半透明の背景を描画します。 image: https://lh3.googleusercontent.com/-SKQis3B-SmY/T0dd531MovI/AAAAAAAABJk/fWIZIAeE3oE/s800/TranslucentPopupMenu.png hreflang:
       href: https://java-swing-tips.blogspot.com/2012/07/translucent-jpopupmenu.html
       lang: en

概要

JPopupMenu自体の背景を透明に設定し、別途そのpaintComponent(...)メソッドをオーバーライドして半透明の背景を描画します。

サンプルコード

class TranslucentPopupMenu extends JPopupMenu {
  private static final Color ALPHA_ZERO = new Color(0x0, true);
  private static final Color POPUP_BACK = new Color(250, 250, 250, 200);
  private static final Color POPUP_LEFT = new Color(230, 230, 230, 200);
  private static final int LEFT_WIDTH = 24;
  @Override public boolean isOpaque() {
    return false;
  }

  @Override public void updateUI() {
    super.updateUI();
    if (UIManager.getBorder("PopupMenu.border") == null) {
      setBorder(new BorderUIResource(BorderFactory.createLineBorder(Color.GRAY)));
    }
  }

  @Override public JMenuItem add(JMenuItem menuItem) {
    menuItem.setOpaque(false);
    // menuItem.setBackground(ALPHA_ZERO);
    return super.add(menuItem);
  }

  @Override public void show(Component c, int x, int y) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        Window p = SwingUtilities.getWindowAncestor(TranslucentPopupMenu.this);
        if (p instanceof JWindow) {
          System.out.println("Heavy weight");
          JWindow w = (JWindow) p;
          w.setBackground(ALPHA_ZERO);
        } else {
          System.out.println("Light weight");
        }
      }
    });
    super.show(c, x, y);
  }

  @Override protected void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(POPUP_LEFT);
    g2.fillRect(0, 0, LEFT_WIDTH, getHeight());
    g2.setPaint(POPUP_BACK);
    g2.fillRect(LEFT_WIDTH, 0, getWidth(), getHeight());
    g2.dispose();
    //super.paintComponent(g);
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、JPopupMenuisOpaque()メソッドをオーバーライド、JMenuItemsetOpaque(false)としてそれぞれ透明に設定し、JPopupMenu#paintComponent(...)で半透明の背景を描画しています。

JPopupMenuが親フレームの外にはみ出す場合はHeavyweightJWindowを使ってJPopupMenuが表示されるので、JWindow#setBackground(new Color(0x0, true))で(JDK 1.6.0_10ではcom.sun.awt.AWTUtilities.setWindowOpaque(w, false))、JPopupMenu#show(...)が呼ばれるたびに毎回(親フレームの透明度を引き継がないように?)JWindow自体を透明にしています。


参考リンク

コメント