• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JPopupMenuを半透明にする
#navi(../)
RIGHT:Posted by [[aterai]] at 2012-02-27
*JPopupMenuを半透明にする [#gcc0b988]
JPopupMenuを半透明にします。
---
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
---
* 概要 [#summary]
`JPopupMenu`自体の背景を透明に設定し、別途その`paintComponent(...)`メソッドをオーバーライドして半透明の背景を描画します。

-&jnlp;
-&jar;
-&zip;
#download(https://lh3.googleusercontent.com/-SKQis3B-SmY/T0dd531MovI/AAAAAAAABJk/fWIZIAeE3oE/s800/TranslucentPopupMenu.png)

//#screenshot
#ref(https://lh3.googleusercontent.com/-SKQis3B-SmY/T0dd531MovI/AAAAAAAABJk/fWIZIAeE3oE/s800/TranslucentPopupMenu.png)

**サンプルコード [#yd15f03c]
#code{{
class TranslucentPopupMenu extends JPopupMenu{
  private static final Color ALPHA_ZERO = new Color(0, 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);
* サンプルコード [#sourcecode]
#code(link){{
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();
    boolean isNimbus = UIManager.getBorder("PopupMenu.border")==null;
    if(isNimbus) {
    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!=null && p instanceof JWindow) {
        if (p instanceof JWindow) {
          System.out.println("Heavy weight");
          JWindow w = (JWindow)p;
          if(System.getProperty("java.version").startsWith("1.6.0")) {
            w.dispose();
            if(com.sun.awt.AWTUtilities.isWindowOpaque(w)) {
              com.sun.awt.AWTUtilities.setWindowOpaque(w, false);
            }
            w.setVisible(true);
          }else{
            w.setBackground(ALPHA_ZERO);
          }
        }else{
          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();
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(POPUP_LEFT);
    g2.fillRect(0,0,LEFT_WIDTH,getHeight());
    g2.fillRect(0, 0, LEFT_WIDTH, getHeight());
    g2.setPaint(POPUP_BACK);
    g2.fillRect(LEFT_WIDTH,0,getWidth(),getHeight());
    g2.fillRect(LEFT_WIDTH, 0, getWidth(), getHeight());
    g2.dispose();
    //super.paintComponent(g);
  }
}
}}

**解説 [#z80cf3e7]
上記のサンプルでは、JPopupMenuは、isOpaque()メソッドをオーバーライド、JMenuItemはsetOpaque(false) として、それぞれ透明に設定し、JPopupMenu#paintComponent(...)で、半透明の背景を描画しています。
* 解説 [#explanation]
上記のサンプルでは、`JPopupMenu`は`isOpaque()`メソッドをオーバーライド、`JMenuItem`は`setOpaque(false)`としてそれぞれ透明に設定し、`JPopupMenu#paintComponent(...)`で半透明の背景を描画しています。

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

**参考リンク [#dcc353c1]
----
- `JPopupMenu`(ルート)が`Light weight`でその`JMenu`から開く`JPopupMenu`(サブメニュー) が`Heavy weight`のときに半透明にならない
-- [https://bugs.openjdk.org/browse/JDK-7156657 JDK-7156657 Version 7 doesn't support translucent popup menus against a translucent window - Java Bug System]
-- `JDK 1.7.0_06`などで修正された

* 参考リンク [#reference]
- [http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html Translucent and Shaped Swing Windows | Java.net]
- [[JMenuなどから開くPopupMenuを半透明化>Swing/TranslucentSubMenu]]

**コメント [#bd72dc66]
* コメント [#comment]
#comment
- メモ: [https://bugs.openjdk.org/browse/JDK-7156657 JDK-7156657 Version 7 doesn't support translucent popup menus against a translucent window - Java Bug System]、[https://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/4acd0211f48b jdk8/jdk8/jdk: changeset 5453:4acd0211f48b] -- &user(aterai); &new{2012-08-10 (金) 19:22:39};
-- `JDK 1.7.0_06`で修正されている? [https://www.oracle.com/java/technologies/javase/7u6-bugfixes.html Java SE Development Kit 7 Update 6 Bug Fixes] -- &user(aterai); &new{2012-08-15 (水) 13:55:37};

#comment