Swing/DropShadowPopup のバックアップソース(No.10)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- バックアップ を表示
- Swing/DropShadowPopup へ行く。
- 1 (2007-03-22 (木) 12:29:12)
- 2 (2007-04-18 (水) 12:39:57)
- 3 (2008-04-10 (木) 18:24:18)
- 4 (2011-04-19 (火) 15:43:56)
- 5 (2011-04-19 (火) 18:55:52)
- 6 (2012-02-05 (日) 14:22:34)
- 7 (2012-02-09 (木) 13:47:39)
- 8 (2012-02-21 (火) 16:45:48)
- 9 (2012-11-23 (金) 04:40:42)
- 10 (2013-02-27 (水) 13:58:49)
- 11 (2013-03-02 (土) 05:32:25)
- 12 (2013-03-04 (月) 09:53:00)
- 13 (2013-03-05 (火) 20:22:26)
- 14 (2013-03-11 (月) 17:09:34)
- 15 (2013-08-09 (金) 13:15:04)
- 16 (2013-08-20 (火) 14:37:23)
- 17 (2013-09-12 (木) 01:13:54)
- 18 (2014-06-10 (火) 18:59:39)
- 19 (2014-09-19 (金) 16:51:25)
- 20 (2014-10-18 (土) 12:45:15)
- 21 (2014-11-25 (火) 03:03:31)
- 22 (2015-02-12 (木) 15:49:13)
- 23 (2015-03-20 (金) 15:23:39)
- 24 (2015-04-04 (土) 22:09:18)
- 25 (2016-01-27 (水) 18:20:45)
- 26 (2016-05-26 (木) 14:50:42)
- 27 (2016-09-20 (火) 04:59:27)
- 28 (2017-03-30 (木) 14:05:39)
- 29 (2017-08-15 (火) 14:13:00)
- 30 (2018-08-16 (木) 15:36:50)
- 31 (2018-12-05 (水) 18:50:12)
- 32 (2020-11-10 (火) 13:48:52)
- 33 (2022-11-06 (日) 20:06:50)
- 34 (2024-02-03 (土) 13:59:47)
TITLE:JPopupMenuに半透明の影を付ける #navi(../) #tags() RIGHT:Posted by &author(aterai); at 2006-07-03 *JPopupMenuに半透明の影を付ける [#z6537cfc] Robotで画面をキャプチャーするなどして、半透明の影をJPopupMenuに付けます。 //-&jnlp; -&jar; -&zip; //#screenshot #ref(http://lh3.ggpht.com/_9Z4BYR88imo/TQTMBgsMvZI/AAAAAAAAAYg/QBh9VXR7P-I/s800/DropShadowPopup.png) **サンプルコード [#q20cf4f0] #code(link){{ class ShadowBorder extends AbstractBorder { private final int xoff, yoff; private final Insets insets; private BufferedImage screen = null; private BufferedImage shadow = null; public ShadowBorder(int x, int y, JComponent c, Point p) { this.xoff = x; this.yoff = y; this.insets = new Insets(0,0,xoff,yoff); try{ Robot robot = new Robot(); Dimension d = c.getPreferredSize(); screen = robot.createScreenCapture( new Rectangle(p.x, p.y, d.width+xoff, d.height+yoff)); }catch (java.awt.AWTException ex) { ex.printStackTrace(); } } @Override public Insets getBorderInsets(Component c) { return insets; } @Override public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { if(screen==null) return; if(shadow==null || shadow.getWidth()!=w || shadow.getHeight()!=h) { shadow = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = shadow.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f)); g2.setPaint(Color.BLACK); for(int i=0;i<xoff;i++) { g2.fillRoundRect(xoff, xoff, w-xoff-xoff+i, h-xoff-xoff+i, 4, 4); } g2.dispose(); } Graphics2D g2d = (Graphics2D)g; g2d.drawImage(screen, 0, 0, c); g2d.drawImage(shadow, 0, 0, c); } } }} **解説 [#te55e54d] ポップアップメニューに半透明の影をつける際、フレームからはみ出すかどうかで異なる処理を行っています。 上記のサンプルコードは、フレームからはみ出す場合に使用するBorderクラスです。 -フレーム内 --JPopupMenu#paintComponentメソッドで半透明の影を描画しています。 -フレーム外 --Robotを使って画面全体をキャプチャーし、これを利用して半透明の影をBorderとして作成しています。このためポップアップメニューがはみ出しても、影を付けることができますが、多少時間が掛かります。 ---- JDK 1.7.0 や、1.6.0_10 以上の場合は、フレーム外でもRobotを使用せず、以下のように JPopupMenu の上位Windowの背景色を透明にすることで影をつけることができます。 #code{{ class DropShadowPopupMenu extends JPopupMenu { private static final int off = 4; private BufferedImage shadow = null; private Border border = null; @Override public boolean isOpaque() { return false; } @Override public void paintComponent(Graphics g) { ((Graphics2D)g).drawImage(shadow, 0, 0, this); super.paintComponent(g); } @Override public void show(Component c, int x, int y) { if(border==null) { Border inner = getBorder(); Border outer = BorderFactory.createEmptyBorder(0, 0, off, off); border = BorderFactory.createCompoundBorder(outer, inner); } setBorder(border); Dimension d = getPreferredSize(); int w = d.width, h = d.height; if(shadow==null || shadow.getWidth()!=w || shadow.getHeight()!=h) { shadow = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = shadow.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f)); g2.setPaint(Color.BLACK); for(int i=0;i<off;i++) { g2.fillRoundRect(off, off, w-off-off+i, h-off-off+i, 4, 4); } g2.dispose(); } EventQueue.invokeLater(new Runnable() { @Override public void run() { Window pop = SwingUtilities.getWindowAncestor(DropShadowPopupMenu.this); if(pop instanceof JWindow) { System.out.println(pop instanceof JWindow); pop.setBackground(new Color(0,0,0,0)); //JDK 1.7.0 //com.sun.awt.AWTUtilities.setWindowOpaque(pop, false); //JDK 1.6.0_10 } } }); super.show(c, x, y); } } }} **参考リンク [#jb8cc361] -[[Menuに半透明の影を付ける>Swing/MenuWithShadow]] **コメント [#e88a4825] - キャプチャーが遅いのは画面全体を撮っているからで、必要なサイズだけにすれば結構速いようです。サンプルを修正してみたところ、毎回キャプチャするようにしても特に気にならない速度で動いてます。 -- [[aterai]] &new{2006-07-18 (火) 12:02:13}; - ソース中でisInRootPanelがおかしい気がするのですが・・・ //convertPointToScreenga -- [[sawshun]] &new{2006-10-05 (木) 11:20:25}; //- #改行しようとしたらコメント入ってしまいました // コメント勝手に修正しました(terai) convertPointToScreenがいらないのと return r.contains(pt)&&r.contains(p) にしないとフレーム内の判定がおかしいようです -- [[sawshun]] &new{2006-10-05 (木) 11:23:39}; -- ご指摘ありがとうごさいます。convertPointToScreenを削除して、MyPopupMenu#isInRootPanelは以下のように修正しました。 -- [[aterai]] &new{2006-10-05 (木) 12:34:12}; #code{{ private boolean isInRootPanel(JComponent root, Point p) { Rectangle r = root.getBounds(); Dimension d = this.getPreferredSize(); //pointed out by sawshun return r.contains(p.x, p.y, d.width+off, d.height+off); } }} - メモ: [http://forums.sun.com/thread.jspa?threadID=590867 Swing - Can popup menu events be consumed by other (e.g. background) components?] -- [[aterai]] &new{2008-04-10 (木) 18:24:18}; #code{{ final MyPopupMenu pop = new MyPopupMenu(); pop.add(new JMenuItem("Open")); pop.add(new JMenuItem("Save")); pop.add(new JMenuItem("Close")); //pop.addSeparator(); //XXX: Nimbus JSeparator s = new JSeparator(); s.setOpaque(true); pop.add(s); pop.add(new JMenuItem("Exit")); JLabel label = new JLabel(icon); label.setComponentPopupMenu(pop); //JDK 1.5 label.addMouseListener(new MouseAdapter() {}); //addMouseListener(new MouseAdapter() { // public void mouseReleased(MouseEvent e) { // if(e.isPopupTrigger()) { // Point pt = e.getPoint(); // pop.show(e.getComponent(), pt.x, pt.y); // } // repaint(); // } //}); }} - Synth(Nimbus) LnF で、JSeparator だけでなく JMenuItem まで透明になった修正?に対応。 -- [[aterai]] &new{2012-02-05 (日) 14:22:34}; - 1.7.0_03でなにか変更があった?のか、変な挙動をするようになったので、調査中。 -- [[aterai]] &new{2012-02-21 (火) 16:45:48}; #comment