Swing/TranslucentPopupMenu のバックアップ(No.5)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - 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を半透明にする
Posted by aterai at 2012-02-27
JPopupMenuを半透明にする
JPopupMenuを半透明にします。
- &jnlp;
- &jar;
- &zip;
サンプルコード
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 void updateUI() {
super.updateUI();
boolean isNimbus = UIManager.getBorder("PopupMenu.border")==null;
if(isNimbus) {
setBorder(new BorderUIResource(BorderFactory.createLineBorder(Color.GRAY)));
}
}
@Override public JMenuItem add(JMenuItem menuItem) {
menuItem.setOpaque(false);
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) {
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{
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();
//super.paintComponent(g);
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、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自体も透明にしています。
参考リンク
- 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が半透明にならない理由が分からない…。
//-*- mode:java; encoding:utf8n; coding:utf-8 -*-
// vim:set fileencoding=utf-8:
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
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();
}
}