Swing/TranslucentPopupMenu のバックアップの現在との差分(No.6)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/TranslucentPopupMenu へ行く。
- 1 (2012-02-27 (月) 14:25:17)
- 2 (2012-07-04 (水) 20:54:31)
- 3 (2012-07-05 (木) 11:43:54)
- 4 (2012-08-10 (金) 19:22:39)
- 5 (2012-08-15 (水) 13:55:37)
- 6 (2012-08-15 (水) 15:31:11)
- 7 (2012-10-17 (水) 16:59:17)
- 8 (2012-10-22 (月) 17:02:28)
- 9 (2012-12-13 (木) 15:29:35)
- 10 (2012-12-25 (火) 18:47:59)
- 11 (2014-11-01 (土) 00:46:09)
- 12 (2014-11-21 (金) 01:19:13)
- 13 (2014-11-26 (水) 02:25:42)
- 14 (2014-12-04 (木) 14:42:22)
- 15 (2015-04-08 (水) 17:12:36)
- 16 (2016-06-01 (水) 18:53:40)
- 17 (2017-09-07 (木) 21:40:17)
- 18 (2018-02-24 (土) 19:51:30)
- 19 (2019-02-22 (金) 20:29:44)
- 20 (2020-12-09 (水) 01:33:04)
- 21 (2022-08-20 (土) 22:15:25)
- 22 (2022-10-04 (火) 15:50:47)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:JPopupMenuを半透明にする #navi(../) RIGHT:Posted by &author(aterai); at 2012-02-27 *JPopupMenuを半透明にする [#gcc0b988] JPopupMenuを半透明にします。 --- category: swing folder: TranslucentPopupMenu title: JPopupMenuを半透明にする tags: [JPopupMenu, JMenuItem, JWindow, Translucent] author: aterai pubdate: 2012-02-27T14:25:17+09:00 description: JPopupMenu自体の背景を透明に設定し、別途そのpaintComponent(...)メソッドをオーバーライドして半透明の背景を描画します。 image: https://lh3.googleusercontent.com/-SKQis3B-SmY/T0dd531MovI/AAAAAAAABJk/fWIZIAeE3oE/s800/TranslucentPopupMenu.png hreflang: href: https://java-swing-tips.blogspot.com/2012/07/translucent-jpopupmenu.html lang: en --- * 概要 [#summary] `JPopupMenu`自体の背景を透明に設定し、別途その`paintComponent(...)`メソッドをオーバーライドして半透明の背景を描画します。 -&jnlp; -&jar; -&zip; #download(https://lh3.googleusercontent.com/-SKQis3B-SmY/T0dd531MovI/AAAAAAAABJk/fWIZIAeE3oE/s800/TranslucentPopupMenu.png) //#screenshot #ref(https://lh3.googleusercontent.com/-SKQis3B-SmY/T0dd531MovI/AAAAAAAABJk/fWIZIAeE3oE/s800/TranslucentPopupMenu.png) **サンプルコード [#yd15f03c] * サンプルコード [#sourcecode] #code(link){{ 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); class TranslucentPopupMenu extends JPopupMenu { private static final Color ALPHA_ZERO = new Color(0x0, 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) { if (UIManager.getBorder("PopupMenu.border") == null) { setBorder(new BorderUIResource(BorderFactory.createLineBorder(Color.GRAY))); } } @Override public JMenuItem add(JMenuItem menuItem) { menuItem.setOpaque(false); // menuItem.setBackground(ALPHA_ZERO); 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) { if (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{ JWindow w = (JWindow) p; 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(); Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(POPUP_LEFT); g2.fillRect(0,0,LEFT_WIDTH,getHeight()); g2.fillRect(0, 0, LEFT_WIDTH, getHeight()); g2.setPaint(POPUP_BACK); g2.fillRect(LEFT_WIDTH,0,getWidth(),getHeight()); g2.fillRect(LEFT_WIDTH, 0, getWidth(), getHeight()); g2.dispose(); //super.paintComponent(g); } } }} **解説 [#z80cf3e7] 上記のサンプルでは、JPopupMenuは、isOpaque()メソッドをオーバーライド、JMenuItemはsetOpaque(false) として、それぞれ透明に設定し、JPopupMenu#paintComponent(...)で、半透明の背景を描画しています。 * 解説 [#explanation] 上記のサンプルでは、`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自体も透明にしています。 `JPopupMenu`が親フレームの外にはみ出す場合は`Heavyweight`の`JWindow`を使って`JPopupMenu`が表示されるので、`JWindow#setBackground(new Color(0x0, true))`で(`JDK 1.6.0_10`では`com.sun.awt.AWTUtilities.setWindowOpaque(w, false)`)、`JPopupMenu#show(...)`が呼ばれるたびに毎回(親フレームの透明度を引き継がないように?)`JWindow`自体を透明にしています。 **参考リンク [#dcc353c1] ---- - `JPopupMenu`(ルート)が`Light weight`でその`JMenu`から開く`JPopupMenu`(サブメニュー) が`Heavy weight`のときに半透明にならない -- [https://bugs.openjdk.org/browse/JDK-7156657 JDK-7156657 Version 7 doesn't support translucent popup menus against a translucent window - Java Bug System] -- `JDK 1.7.0_06`などで修正された * 参考リンク [#reference] - [http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html Translucent and Shaped Swing Windows | Java.net] -- メモ: PopupFactoryを継承するTranslucentPopupFactoryを作成して、PopupFactory.setSharedInstance(new TranslucentPopupFactory())と設定する方法 -- 以下、JMenuから開いたJPopupMenuも半透明にできないか、TranslucentPopupFactoryを使う方法をテスト中。 --- PopupFactory.setSharedInstance(new TranslucentPopupFactory());としないと、ルートJPopupMenuがLight weightで、JMenuのJPopupMenuがHeavy weightのときに、JMenuのJPopupMenuが半透明にならない理由が分からない…。 ---- JDK 1.7.0_04, Windows 7 でテスト中 - [[JMenuなどから開くPopupMenuを半透明化>Swing/TranslucentSubMenu]] #code{{ //-*- mode:java; encoding:utf8n; coding:utf-8 -*- // vim:set fileencoding=utf-8: import java.awt.*; import javax.swing.*; import javax.swing.plaf.*; * コメント [#comment] #comment - メモ: [https://bugs.openjdk.org/browse/JDK-7156657 JDK-7156657 Version 7 doesn't support translucent popup menus against a translucent window - Java Bug System]、[https://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/4acd0211f48b jdk8/jdk8/jdk: changeset 5453:4acd0211f48b] -- &user(aterai); &new{2012-08-10 (金) 19:22:39}; -- `JDK 1.7.0_06`で修正されている? [https://www.oracle.com/java/technologies/javase/7u6-bugfixes.html Java SE Development Kit 7 Update 6 Bug Fixes] -- &user(aterai); &new{2012-08-15 (水) 13:55:37}; public class TranslucentMenuTest { private final JComponent tree = new JTree(); public JComponent makeUI() { tree.setComponentPopupMenu(makePopupMenu()); JPanel p = new JPanel(new BorderLayout()); p.add(new JScrollPane(tree)); return p; } private static JPopupMenu makePopupMenu() { JMenu menu = new TransparentMenu("Test"); menu.add(new JMenuItem("Undo")); menu.add(new JMenuItem("Redo")); JPopupMenu popup = new TranslucentPopupMenu(); popup.add(menu); popup.addSeparator(); popup.add(new JMenuItem("Cut")); popup.add(new JMenuItem("Copy")); popup.add(new JMenuItem("Paste")); popup.add(new JMenuItem("Delete")); return popup; } 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(); } PopupFactory.setSharedInstance(new TranslucentPopupFactory()); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.getContentPane().add(new TranslucentMenuTest().makeUI()); frame.setSize(320, 240); frame.setLocationRelativeTo(null); frame.setVisible(true); } } //http://terai.xrea.jp/Swing/TranslucentPopupMenu.html 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 Component add(Component c) { if(c instanceof JComponent) { ((JComponent)c).setOpaque(false); } return c; } @Override public JMenuItem add(JMenuItem menuItem) { menuItem.setOpaque(false); return super.add(menuItem); } @Override public void show(Component c, int x, int y) { Window p = SwingUtilities.getWindowAncestor(TranslucentPopupMenu.this); if(p!=null && p instanceof JWindow) { System.out.println("Heavy weight"); ((JWindow)p).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(); } } 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) { final JMenu thisMenu = this; //this.popupMenu = new JPopupMenu(); this.popupMenu = new TranslucentPopupMenu(); popupMenu.setOpaque(false); 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(); } } /* <a href="http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html"> Translucent and Shaped Swing Windows | Java.net </a> */ 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); } } class TranslucentPopup extends Popup { private JWindow popupWindow; public TranslucentPopup(Component owner, Component contents, int ownerX, int ownerY) { // create a new heavyweight window this.popupWindow = new JWindow(); // mark the popup with partial opacity //com.sun.awt.AWTUtilities.setWindowOpacity(popupWindow, (contents instanceof JToolTip) ? 0.8f : 0.95f); //popupWindow.setOpacity(.5f); popupWindow.setBackground(new Color(0, true)); // determine the popup location popupWindow.setLocation(ownerX, ownerY); // add the contents to the popup popupWindow.getContentPane().add(contents); contents.invalidate(); //JComponent parent = (JComponent) contents.getParent(); // set the shadow border //parent.setBorder(new ShadowPopupBorder()); } @Override public void show() { this.popupWindow.setVisible(true); this.popupWindow.pack(); // mark the window as non-opaque, so that the // shadow border pixels take on the per-pixel // translucency //com.sun.awt.AWTUtilities.setWindowOpaque(this.popupWindow, false); //popupWindow.setBackground(new Color(0,0,0,0)); } @Override public void hide() { this.popupWindow.setVisible(false); this.popupWindow.removeAll(); this.popupWindow.dispose(); } } }} **コメント [#bd72dc66] - メモ: [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]、[http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/4acd0211f48b jdk8/jdk8/jdk: changeset 5453:4acd0211f48b] -- [[aterai]] &new{2012-08-10 (金) 19:22:39}; -- 1.7.0_06 で修正されている? [http://www.oracle.com/technetwork/java/javase/2col/7u6-bugfixes-1733378.html Java™ SE Development Kit 7 Update 6 Bug Fixes] -- [[aterai]] &new{2012-08-15 (水) 13:55:37}; #comment