TITLE:JPopupMenuを半透明にする

Posted by at 2012-02-27

JPopupMenuを半透明にする

JPopupMenuを半透明にします。

  • &jnlp;
  • &jar;
  • &zip;
TranslucentPopupMenu.png

サンプルコード

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);
  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) {
      setBorder(new BorderUIResource(BorderFactory.createLineBorder(Color.GRAY)));
    }
  }
  @Override public JMenuItem add(JMenuItem menuItem) {
    menuItem.setOpaque(false);
    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) {
          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{
          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

解説

上記のサンプルでは、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自体も透明にしています。

参考リンク

コメント