Swing/TranslucentSubMenu のバックアップソース(No.4)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - 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)
TITLE:JMenuなどから開くPopupMenuを半透明化 #navi(../) RIGHT:Posted by &author(aterai); at 2012-10-22 *JMenuなどから開くPopupMenuを半透明化 [#ia005766] ``JPopupMenu``の親の``JWindow``、``JMenu``や``JMenuItem``などを透明にして、``JPopupMenu``を半透明にします。 -&jnlp; -&jar; -&zip; //#screenshot #ref(https://lh5.googleusercontent.com/-MKRZgWcSrRw/UIT3NRGfX9I/AAAAAAAABUk/fOYdfJmIt4g/s800/TranslucentSubMenu.png) **サンプルコード [#v7863f10] #code(link){{ class TransparentMenu extends JMenu { public TransparentMenu(String title) { super(title); } //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=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(); } } }} **解説 [#p928b03d] 上記のサンプルでは、``JMenu``を継承する``TransparentMenu``を作成して、自身と``JMenuItem``などを透明化し、``JMenu``から開く``JPopupMenu``は、[[JPopupMenuを半透明にする>Swing/TranslucentPopupMenu]]を使用して半透明にしています。 - ``JPopupMenu``の親の透明化 -- [http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html Translucent and Shaped Swing Windows | Java.net] を参考に ``PopupFactory#getPopup(...)``をオーバーライドし、常に``JPopupMenu``(半透明)の親に``JWindow``(完全に透明、``Heavy weight``)を使用するように設定 #code{{ PopupFactory.setSharedInstance(new TranslucentPopupFactory()); }} #code{{ 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を半透明にする>Swing/TranslucentPopupMenu]]の場合は、JPopupMenu#show(...)メソッドをオーバーライドし、ポップアップが親フレームからはみ出して ``Heavy weight``の``JWindow``が親として使用される時にだけ、``JWindow#setBackground(ALPHA_ZERO)``などで透明化(``JPopupMenu``は半透明)しているが、[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7156657 Bug ID: 7156657 Version 7 doesn't support translucent popup menus against a translucent window] が原因?で、``1.7.0_06``以前では、サブメニューが半透明化されない場合がある --- ``PopupFactory.setSharedInstance(new TranslucentPopupFactory())``では、バグの影響を受けない --- 上記のバグ?以外にも、[[JPopupMenuを半透明にする>Swing/TranslucentPopupMenu]]でサブメニューを半透明にする場合、``Heavy weight``の``JPopupMenu``に使用する``JWindow``の``ContentPane``と``JRootPane``の不透明設定(``isOpaque()``)に注意する必要がある ---- 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 #code{{ 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) { //... }} **参考リンク [#s17a0f91] - [http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html Translucent and Shaped Swing Windows | Java.net] - [http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7156657 Bug ID: 7156657 Version 7 doesn't support translucent popup menus against a translucent window] - [[JPopupMenuを半透明にする>Swing/TranslucentPopupMenu]] **コメント [#iea685f4] - [http://bugs.sun.com/bugdatabase/ Java Bug Database]の見た目が新しくなっている? Fixed Versions の表示がシンプルになりすぎているような…。 -- [[aterai]] &new{2012-10-22 (月) 20:22:51}; #comment