Swing/TranslucentSubMenu のバックアップ(No.13)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/TranslucentSubMenu へ行く。
- 1 (2012-10-22 (月) 18:38:06)
- 2 (2012-10-22 (月) 20:22:51)
- 3 (2012-12-06 (木) 12:15:23)
- 4 (2012-12-07 (金) 16:40:20)
- 5 (2012-12-25 (火) 23:11:35)
- 6 (2012-12-26 (水) 11:24:59)
- 7 (2014-11-01 (土) 00:46:09)
- 8 (2014-12-11 (木) 15:09:07)
- 9 (2015-02-22 (日) 21:04:31)
- 10 (2016-07-20 (水) 20:33:11)
- 11 (2017-09-27 (水) 19:04:28)
- 12 (2017-11-02 (木) 15:34:40)
- 13 (2019-05-22 (水) 19:35:38)
- 14 (2019-06-11 (火) 19:44:14)
- 15 (2021-02-24 (水) 06:02:07)
- 16 (2022-08-20 (土) 22:15:25)
- category: swing folder: TranslucentSubMenu title: JMenuなどから開くPopupMenuを半透明化 tags: [JMenu, JMenuItem, JPopupMenu, Translucent] author: aterai pubdate: 2012-10-22T18:38:06+09:00 description: JPopupMenuの親のJWindow、JMenuやJMenuItemなどを透明にして、JPopupMenuを半透明にします。 image:
概要
JPopupMenu
の親のJWindow
、JMenu
やJMenuItem
などを透明にして、JPopupMenu
を半透明にします。
Screenshot
Advertisement
サンプルコード
class TransparentMenu extends JMenu {
public TransparentMenu(String title) {
super(title);
}
//https://bugs.openjdk.java.net/browse/JDK-4688783
private JPopupMenu popupMenu;
private void ensurePopupMenuCreated() {
if (popupMenu == null) {
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();
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JMenu
を継承するTransparentMenu
を作成し、JMenu
自身と子のJMenuItem
などを透明化しています。またJMenu
から開くJPopupMenu
も、JPopupMenuを半透明にするを使用して半透明になるよう設定しています。
- Translucent and Shaped Swing Windows | Java.net を参考に
PopupFactory#getPopup(...)
をオーバーライドし、常にJPopupMenu
(半透明)の親にJWindow
(完全に透明、Heavy weight
)を使用するように設定
PopupFactory.setSharedInstance(new TranslucentPopupFactory());
//...
class TranslucentPopupFactory extends PopupFactory {
@Override public Popup getPopup(Component owner, Component contents, int x, int y)
throws IllegalArgumentException {
return new TranslucentPopup(owner, contents, x, y);
}
}
- JPopupMenuを半透明にするでは、
JPopupMenu#show(...)
メソッドをオーバーライドし、ポップアップが親フレームからはみ出してHeavy weight
のJWindow
がJPopupMenu
の親となる場合のみ、JWindow#setBackground(ALPHA_ZERO)
などで透明化(JPopupMenu
は半透明)- Bug ID: 7156657 Version 7 doesn't support translucent popup menus against a translucent window が原因?で、
1.7.0_06
以前では、サブメニューが半透明化されない場合がある PopupFactory.setSharedInstance(new TranslucentPopupFactory())
を使用する場合はバグの影響を受けない- 上記のバグ?以外にも、JPopupMenuを半透明にするでサブメニューを半透明にする場合、
Heavy weight
のJPopupMenu
に使用するJWindow
のContentPane
とJRootPane
の不透明設定(isOpaque()
)に注意する必要がある
- Bug ID: 7156657 Version 7 doesn't support translucent popup menus against a translucent window が原因?で、
---- HeavyWeightWindow: win0, JPopupMenu: base javax.swing.JPanel: false javax.swing.JLayeredPane: false javax.swing.JRootPane: false ---- HeavyWeightWindow: win1, JPopupMenu: sub javax.swing.JPanel: true javax.swing.JLayeredPane: false javax.swing.JRootPane: true
class TranslucentPopupMenu extends JPopupMenu {
@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) {
JWindow w = (JWindow) p;
w.setBackground(ALPHA_ZERO);
System.out.format("HeavyWeightWindow: %s, JPopupMenu: %s\n", w.getName(), getName());
Container c = (Container) w.getContentPane();
while (c != null && c instanceof JComponent) {
JComponent jc = (JComponent) c;
System.out.format("%s: %s\n", c.getClass().getName(), jc.isOpaque());
if (jc.isOpaque()) {
jc.setOpaque(false);
}
c = c.getParent();
}
} else {
System.out.println("Light weight");
}
}
});
super.show(c, x, y);
}
@Override protected void paintComponent(Graphics g) {
//...
参考リンク
- Translucent and Shaped Swing Windows | Java.net
- JDK-7156657 Version 7 doesn't support translucent popup menus against a translucent window
- JPopupMenuを半透明にする
- JRootPaneの背景として画像を表示