TITLE:JMenuBarの背景に画像を表示する
Posted by aterai at 2009-08-10

JMenuBarの背景に画像を表示する

JMenuBarの背景に画像を表示します。
  • category: swing folder: MenuBarBackground title: JMenuBarの背景に画像を表示する tags: [JMenuBar, JMenu, JMenuItem, TexturePaint] author: aterai pubdate: 2009-08-10T15:27:32+09:00 description: JMenuが未選択状態の場合はその背景を透明にし、JMenuBarの背景に設定した画像を表示可能にします。 image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTPxQA13fI/AAAAAAAAAeg/SAN79wHPkQc/s800/MenuBarBackground.png hreflang:
       href: https://java-swing-tips.blogspot.com/2009/08/jmenubar-background-image.html
       lang: en

概要

JMenuが未選択状態の場合はその背景を透明にし、JMenuBarの背景に設定した画像を表示可能にします。
MenuBarBackground.png

サンプルコード

#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
public JMenuBar createMenubar() {
  final TexturePaint texture = makeTexturePaint();
  JMenuBar mb = new JMenuBar() {
    @Override protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)g;
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setPaint(texture);
      g2.fillRect(0, 0, getWidth(), getHeight());
      g2.dispose();
    }
  };
  mb.setOpaque(false);
  String[] menuKeys = {"File", "Edit", "Help"};
  for(String key: menuKeys) {
  for (String key: menuKeys) {
    JMenu m = createMenu(key);
    if(m != null) mb.add(m);
    if (m != null) {
      mb.add(m);
    }
  }
  return mb;
}
#spanadd

#spanend
private JMenu createMenu(String key) {
  JMenu menu = new JMenu(key) {
    @Override protected void fireStateChanged() {
      ButtonModel m = getModel();
      if(m.isPressed() && m.isArmed()) {
      if (m.isPressed() && m.isArmed()) {
        setOpaque(true);
      }else if(m.isSelected()) {
      } else if (m.isSelected()) {
        setOpaque(true);
      }else if(isRolloverEnabled() && m.isRollover()) {
      } else if (isRolloverEnabled() && m.isRollover()) {
        setOpaque(true);
      }else{
      } else {
        setOpaque(false);
      }
      super.fireStateChanged();
    };
  };
  if("Windows XP".equals(System.getProperty("os.name"))) {
    menu.setBackground(new Color(0,0,0,0)); //XXX Windows XP lnf?
  if ("Windows XP".equals(System.getProperty("os.name"))) {
    menu.setBackground(new Color(0x0, true)); // XXX: Windows XP lnf?
  }
  menu.add("dummy1"); menu.add("dummy2"); menu.add("dummy3");
  menu.add("JMenuItem1");
  menu.add("JMenuItem2");
  menu.add("JMenuItem3");
  return menu;
}

解説

上記のサンプルでは、JMenuBarに画像を描画し、これに追加するJMenuを通常は透明、選択されたときなどは不透明となるようにsetOpaqueメソッドで切り替えています。

解説

上記のサンプルでは、JMenuBarに画像を描画し、これに追加するJMenuを通常は透明、選択されたときなどは不透明となるようにsetOpaqueメソッドで切り替えています。
  • 注意点
    • Windows LnF の場合、JMenu#setBackground(new Color(0,0,0,0)); とする必要がある?
    • Nimbus LnF には対応していない
    • Windows LnF に切り替えた直後、メニューの文字色などがおかしい?
  • WindowsLookAndFeelの場合、JMenu#setBackground(new Color(0x0, true))を設定する必要がある
  • WindowsLookAndFeelに切り替えた直後のメニュー文字色などがおかしい?

JFrame#setJMenuBar()で追加したJMenuBarを透明にする場合のテスト(NimbusLnF)
  • 以下はJFrame#setJMenuBar()で追加したJMenuBarを透明にする場合のテスト
import java.awt.*;
import java.awt.image.*;
#spanadd
import java.util.Objects;
#spanend
import javax.swing.*;
#spandel
public class MenuBarRootPaneTest{
#spanend
  private static JMenuBar createMenubar() {
    JMenuBar mb = new JMenuBar();
    mb.setOpaque(false);
    mb.setBackground(new Color(0,0,0,0));
#spanadd
import javax.swing.plaf.*;
#spanend
#spanadd

#spanend
#spanadd
public class MenuBarRootPaneTest {
#spanend
  private static final Color ALPHA_ZERO = new Color(0x0, true);
  private static final Color POPUP_BACK = new Color(0, 0, 0, 100);
#spanadd

#spanend
  private static JMenuBar createMenuBar() {
    JMenuBar mb = new JMenuBar() {
        @Override public Dimension getPreferredSize() {
            Dimension d = super.getPreferredSize();
            d.height = 30;
            return d;
        }
    };
    mb.setBackground(POPUP_BACK);
    String[] menuKeys = {"File", "Edit", "Help"};
    for(String key: menuKeys) {
      JMenu m = createMenu(key);
      if(m != null) mb.add(m);
    for (String key : menuKeys) {
      mb.add(createMenu(key));
    }
    return mb;
  }
#spanadd

#spanend
  private static JMenu createMenu(String key) {
    JMenu menu = new JMenu(key);
    menu.setForeground(Color.WHITE);
    menu.add("dummy1"); menu.add("dummy2"); menu.add("dummy3");
    JMenu menu = new TransparentMenu(key);
    menu.add(new JMenuItem("JMenuItem1"));
    menu.add(new JMenuItem("JMenuItem2"));
    menu.add(new JMenuItem("JMenuItem3"));
    return menu;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
#spanadd

#spanend
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      UIManager.put("MenuBar.background", POPUP_BACK);
      UIManager.put("MenuBar.border", BorderFactory.createEmptyBorder());
      UIManager.put("PopupMenu.border", BorderFactory.createEmptyBorder());
#spanadd

#spanend
      UIManager.put("Menu.foreground", Color.WHITE);
      UIManager.put("Menu.background", ALPHA_ZERO);
      UIManager.put("Menu.selectionBackground", POPUP_BACK);
      UIManager.put("Menu.selectionForeground", Color.WHITE);
      UIManager.put("Menu.borderPainted", Boolean.FALSE);
#spanadd

#spanend
      UIManager.put("MenuItem.foreground", Color.WHITE);
      UIManager.put("MenuItem.background", ALPHA_ZERO);
      UIManager.put("MenuItem.selectionBackground", POPUP_BACK);
      UIManager.put("MenuItem.selectionForeground", Color.WHITE);
      UIManager.put("MenuItem.borderPainted", Boolean.FALSE);
#spanadd

#spanend
      JFrame frame = new JFrame() {
        @Override protected JRootPane createRootPane() {
          return new JRootPane() {
            private final TexturePaint texture = makeTexturePaint();
            @Override protected void paintComponent(Graphics g) {
              super.paintComponent(g);
              Graphics2D g2 = (Graphics2D) g.create();
              g2.setPaint(texture);
              g2.fillRect(0, 0, getWidth(), getHeight());
              g2.dispose();
            }
#spanadd

#spanend
            @Override public boolean isOpaque() {
              return true;
            }
          };
        }
      };
      frame.getRootPane().setBackground(Color.BLUE);
      frame.getLayeredPane().setBackground(Color.GREEN);
      frame.getContentPane().setBackground(Color.RED);
      ((JComponent) frame.getContentPane()).setOpaque(false);
      frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      frame.setJMenuBar(createMenuBar());
      frame.setSize(320, 240);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    });
  }
  public static void createAndShowGUI() {
    try {
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
        if ("Nimbus".equals(laf.getName()))
          UIManager.setLookAndFeel(laf.getClassName());
    }catch(Exception e) {
      e.printStackTrace();
#spanadd

#spanend
  // TranslucentPopupMenu
  // https://ateraimemo.com/Swing/TranslucentPopupMenu.html
  static class TranslucentPopupMenu extends JPopupMenu {
    @Override public boolean isOpaque() {
      return false;
    }
    JFrame frame = new JFrame();
    frame.getRootPane().setBackground(Color.RED);
    //frame.getLayeredPane().setBackground(Color.GREEN);
    //frame.getContentPane().setBackground(Color.BLUE);
    ((JComponent)frame.getContentPane()).setOpaque(false);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setJMenuBar(createMenubar());
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
#spanadd

#spanend
    @Override public void show(Component c, int x, int y) {
      EventQueue.invokeLater(() -> {
        Container p = getTopLevelAncestor();
        if (p instanceof JWindow) {
          System.out.println("Heavy weight");
          ((JWindow) p).setBackground(ALPHA_ZERO);
        }
      });
      super.show(c, x, y);
    }
#spanadd

#spanend
    @Override protected void paintComponent(Graphics g) {
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setPaint(POPUP_BACK);
      g2.fillRect(0, 0, getWidth(), getHeight());
      g2.dispose();
    }
  }
#spandel
}
#spanend
#spandel

コメント

  • 選択状態を半透明にするテスト -- aterai
    #spanend
    #spandel
    import java.awt.*;
    #spanend
    #spandel
    import java.awt.event.*;
    #spanend
    #spandel
    import java.awt.image.*;
    #spanend
    #spandel
    import java.awt.geom.*;
    #spanend
    #spandel
    import javax.swing.*;
    #spanend
    #spandel
    public class MenuBarBackgroundTest {
    #spanend
      public JComponent makeUI() {
        final TexturePaint texture = makeTexturePaint();
        JPanel p = new JPanel(new BorderLayout()) {
          @Override protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setPaint(texture);
            g2.fillRect(0, 0, getWidth(), getHeight());
      static class TransparentMenu extends JMenu {
        private JPopupMenu popupMenu;
    #spanadd
    
    #spanend
        protected TransparentMenu(String title) {
          super(title);
        }
    #spanadd
    
    #spanend
        @Override public boolean isOpaque() {
          return false;
        }
    #spanadd
    
    #spanend
        // Bug ID: JDK-4688783 JPopupMenu hardcoded i JMenu
        // https://bugs.openjdk.org/browse/JDK-4688783
        private void ensurePopupMenuCreated() {
          if (Objects.isNull(popupMenu)) {
            this.popupMenu = new TranslucentPopupMenu();
            popupMenu.setInvoker(this);
            popupListener = createWinListener(popupMenu);
          }
        };
        p.setOpaque(false);
        p.add(createMenubar(), BorderLayout.NORTH);
        return p;
      }
      public static JMenuBar createMenubar() {
        UIManager.put("Menu.background", new Color(200,0,0,0));
        UIManager.put("Menu.selectionBackground", new Color(0,0,100,100));
        UIManager.put("Menu.selectionForeground", new Color(200,0,0));
        UIManager.put("Menu.useMenuBarBackgroundForTopLevel", Boolean.TRUE);
        JMenuBar mb = new JMenuBar() {
          private final TexturePaint texture = makeTexturePaint();
          @Override protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setPaint(texture);
            g2.fillRect(0, 0, getWidth(), getHeight());
        }
    #spanadd
    
    #spanend
        @Override public JPopupMenu getPopupMenu() {
          ensurePopupMenuCreated();
          return popupMenu;
        }
    #spanadd
    
    #spanend
        @Override public JMenuItem add(JMenuItem menuItem) {
          ensurePopupMenuCreated();
          menuItem.setOpaque(false);
          return popupMenu.add(menuItem);
        }
    #spanadd
    
    #spanend
        @Override public Component add(Component c) {
          ensurePopupMenuCreated();
          if (c instanceof JComponent) {
            ((JComponent) c).setOpaque(false);
          }
        };
        mb.setOpaque(false);
        mb.setOpaque(false);
        for(String key: new String[] {"File", "Edit", "Help"}) {
          JMenu m = createMenu(key);
          if(m != null) mb.add(m);
          popupMenu.add(c);
          return c;
        }
        return mb;
    #spanadd
    
    #spanend
        @Override public void addSeparator() {
          ensurePopupMenuCreated();
          popupMenu.addSeparator();
        }
    #spanadd
    
    #spanend
        @Override public void insert(String s, int pos) {
          if (pos < 0) {
            throw new IllegalArgumentException("index less than zero.");
          }
          ensurePopupMenuCreated();
          popupMenu.insert(new JMenuItem(s), pos);
        }
    #spanadd
    
    #spanend
        @Override public JMenuItem insert(JMenuItem mi, int pos) {
          if (pos < 0) {
            throw new IllegalArgumentException("index less than zero.");
          }
          ensurePopupMenuCreated();
          popupMenu.insert(mi, pos);
          return mi;
        }
    #spanadd
    
    #spanend
        @Override public void insertSeparator(int index) {
          if (index < 0) {
            throw new IllegalArgumentException("index less than zero.");
          }
          ensurePopupMenuCreated();
          popupMenu.insert(new JPopupMenu.Separator(), index);
        }
    #spanadd
    
    #spanend
        @Override public boolean isPopupMenuVisible() {
          ensurePopupMenuCreated();
          return popupMenu.isVisible();
        }
      }
      private static JMenu createMenu(String key) {
        final JMenu menu = new JMenu(key);
        menu.add("dummy1");
        menu.add("dummy2");
        menu.add("dummy3");
        return menu;
      }
    #spanadd
    
    #spanend
      private static TexturePaint makeTexturePaint() {
        int cs = 6, sz = cs*cs;
        BufferedImage img = new BufferedImage(sz,sz,BufferedImage.TYPE_4BYTE_ABGR);
        int cs = 6;
        int sz = cs * cs;
        BufferedImage img = new BufferedImage(sz, sz, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        g2.setPaint(new Color(200,150,100,50));
        g2.fillRect(0,0,sz,sz);
        for(int i=0; i*cs<sz; i++) {
          for(int j=0; j*cs<sz; j++) {
            if((i+j)%2==0) g2.fillRect(i*cs, j*cs, cs, cs);
        g2.setPaint(new Color(222, 222, 222, 50));
        g2.fillRect(0, 0, sz, sz);
        for (int i = 0; i * cs < sz; i++) {
          for (int j = 0; j * cs < sz; j++) {
            if ((i + j) % 2 == 0) {
              g2.fillRect(i * cs, j * cs, cs, cs);
            }
          }
        }
        g2.dispose();
        return new TexturePaint(img, new Rectangle(0,0,sz,sz));
        return new TexturePaint(img, new Rectangle(sz, sz));
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() {
            createAndShowGUI();
          }
        });
      }
      public static void createAndShowGUI() {
        try {
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch(Exception e) {
          e.printStackTrace();
        }
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MenuBarBackgroundTest().makeUI());
        frame.setSize(320,240);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    }
    #spanadd
    
    #spanend
    #spanadd
    // //https://ateraimemo.com/Swing/TranslucentPopupMenu.html
    #spanend
    #spanadd
    // class TranslucentPopupMenu extends JPopupMenu {
    #spanend
    
  • Windows7 のLnFでうまくいかない場合があるようなので、すこし修正。 -- aterai

参考リンク

コメント