Swing/MenuBarBackground のバックアップ(No.27)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/MenuBarBackground へ行く。
- 1 (2009-08-10 (月) 15:27:32)
- 2 (2010-01-09 (土) 23:08:42)
- 3 (2010-06-10 (木) 15:34:46)
- 4 (2011-05-10 (火) 23:27:28)
- 5 (2011-09-26 (月) 21:12:32)
- 6 (2011-10-11 (火) 17:11:08)
- 7 (2011-10-19 (水) 00:35:36)
- 8 (2011-12-20 (火) 18:08:56)
- 9 (2012-02-28 (火) 21:24:03)
- 10 (2013-01-06 (日) 21:32:50)
- 11 (2013-01-07 (月) 00:33:12)
- 12 (2013-02-26 (火) 19:51:14)
- 13 (2014-11-20 (木) 01:49:24)
- 14 (2014-11-30 (日) 00:52:48)
- 15 (2015-01-25 (日) 18:28:41)
- 16 (2015-04-01 (水) 20:09:52)
- 17 (2015-04-05 (日) 23:10:01)
- 18 (2016-01-17 (日) 02:07:31)
- 19 (2016-07-20 (水) 20:41:36)
- 20 (2016-07-20 (水) 22:02:52)
- 21 (2017-09-27 (水) 19:01:44)
- 22 (2017-10-27 (金) 16:26:13)
- 23 (2017-11-02 (木) 15:38:08)
- 24 (2018-02-24 (土) 19:51:30)
- 25 (2018-05-31 (木) 14:36:14)
- 26 (2020-05-22 (金) 17:41:59)
- 27 (2021-11-10 (水) 12:39:18)
- 28 (2022-08-20 (土) 22:15:25)
- 29 (2024-02-09 (金) 13:57:13)
- 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:
hreflang:
href: https://java-swing-tips.blogspot.com/2009/08/jmenubar-background-image.html lang: en
概要
JMenu
が未選択状態の場合はその背景を透明にし、JMenuBar
の背景に設定した画像を表示可能にします。
Screenshot
Advertisement
サンプルコード
public JMenuBar createMenubar() {
final TexturePaint texture = makeTexturePaint();
JMenuBar mb = new JMenuBar() {
@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();
}
};
mb.setOpaque(false);
String[] menuKeys = {"File", "Edit", "Help"};
for (String key: menuKeys) {
JMenu m = createMenu(key);
if (m != null) {
mb.add(m);
}
}
return mb;
}
private JMenu createMenu(String key) {
JMenu menu = new JMenu(key) {
@Override protected void fireStateChanged() {
ButtonModel m = getModel();
if (m.isPressed() && m.isArmed()) {
setOpaque(true);
} else if (m.isSelected()) {
setOpaque(true);
} else if (isRolloverEnabled() && m.isRollover()) {
setOpaque(true);
} else {
setOpaque(false);
}
super.fireStateChanged();
};
};
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");
return menu;
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JMenuBar
に画像を描画し、これに追加するJMenu
を通常は透明、選択されたときなどは不透明となるようにsetOpaque
メソッドで切り替えています。
WindowsLookAndFeel
の場合、JMenu#setBackground(new Color(0x0, true))
を設定する必要があるWindowsLookAndFeel
に切り替えた直後のメニュー文字色などがおかしい?
JFrame#setJMenuBar()
で追加したJMenuBar
を透明にする場合のテスト
import java.awt.*;
import java.awt.image.*;
import java.util.Objects;
import javax.swing.*;
import javax.swing.plaf.*;
public class MenuBarRootPaneTest {
private static final Color ALPHA_ZERO = new Color(0x0, true);
private static final Color POPUP_BACK = new Color(0, 0, 0, 100);
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) {
mb.add(createMenu(key));
}
return mb;
}
private static JMenu createMenu(String key) {
JMenu menu = new TransparentMenu(key);
menu.add(new JMenuItem("dummy1"));
menu.add(new JMenuItem("dummy2"));
menu.add(new JMenuItem("dummy3"));
return menu;
}
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());
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);
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);
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();
}
@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);
});
}
// TranslucentPopupMenu
// https://ateraimemo.com/Swing/TranslucentPopupMenu.html
static class TranslucentPopupMenu extends JPopupMenu {
@Override public boolean isOpaque() {
return false;
}
@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);
}
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(POPUP_BACK);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.dispose();
}
}
static class TransparentMenu extends JMenu {
private JPopupMenu popupMenu;
protected TransparentMenu(String title) {
super(title);
}
@Override public boolean isOpaque() {
return false;
}
// Bug ID: JDK-4688783 JPopupMenu hardcoded i JMenu
// https://bugs.openjdk.java.net/browse/JDK-4688783
private void ensurePopupMenuCreated() {
if (Objects.isNull(popupMenu)) {
this.popupMenu = new TranslucentPopupMenu();
popupMenu.setInvoker(this);
popupListener = createWinListener(popupMenu);
}
}
@Override public JPopupMenu getPopupMenu() {
ensurePopupMenuCreated();
return popupMenu;
}
@Override public JMenuItem add(JMenuItem menuItem) {
ensurePopupMenuCreated();
menuItem.setOpaque(false);
return popupMenu.add(menuItem);
}
@Override public Component add(Component c) {
ensurePopupMenuCreated();
if (c instanceof JComponent) {
((JComponent) c).setOpaque(false);
}
popupMenu.add(c);
return c;
}
@Override public void addSeparator() {
ensurePopupMenuCreated();
popupMenu.addSeparator();
}
@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);
}
@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;
}
@Override public void insertSeparator(int index) {
if (index < 0) {
throw new IllegalArgumentException("index less than zero.");
}
ensurePopupMenuCreated();
popupMenu.insert(new JPopupMenu.Separator(), index);
}
@Override public boolean isPopupMenuVisible() {
ensurePopupMenuCreated();
return popupMenu.isVisible();
}
}
private static TexturePaint makeTexturePaint() {
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(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(sz, sz));
}
}
// //https://ateraimemo.com/Swing/TranslucentPopupMenu.html
// class TranslucentPopupMenu extends JPopupMenu {