Swing/TranslucentPopupMenu のバックアップの現在との差分(No.3)
TITLE:JPopupMenuを半透明にする
Posted by aterai at 2012-02-27
JPopupMenuを半透明にする
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:
hreflang:
href: https://java-swing-tips.blogspot.com/2012/07/translucent-jpopupmenu.html lang: en
概要
JPopupMenu
自体の背景を透明に設定し、別途そのpaintComponent(...)
メソッドをオーバーライドして半透明の背景を描画します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
サンプルコード
#spandel
class TranslucentPopupMenu extends JPopupMenu{
#spanend
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);
#spanadd
class TranslucentPopupMenu extends JPopupMenu {
#spanend
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;
}
#spanadd
#spanend
@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)));
}
}
#spanadd
#spanend
@Override public JMenuItem add(JMenuItem menuItem) {
menuItem.setOpaque(false);
// menuItem.setBackground(ALPHA_ZERO);
return super.add(menuItem);
}
#spanadd
#spanend
@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);
}
#spanadd
#spanend
@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);
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JPopupMenuは、isOpaque()メソッドをオーバーライド、JMenuItemはsetOpaque(false) として、それぞれ透明に設定し、JPopupMenu#paintComponent(...)で、半透明の背景を描画しています。解説
上記のサンプルでは、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
自体を透明にしています。
参考リンク
- -
-
JPopupMenu
(ルート)がLight weight
でそのJMenu
から開くJPopupMenu
(サブメニュー) がHeavy weight
のときに半透明にならない
参考リンク
- 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が半透明にならない理由が分からない…。
- JMenuなどから開くPopupMenuを半透明化
#spanend
#spandel
//package example;
#spanend
#spandel
//-*- mode:java; encoding:utf8n; coding:utf-8 -*-
#spanend
#spandel
// vim:set fileencoding=utf-8:
#spanend
#spandel
//@homepage@
#spanend
#spandel
import java.awt.*;
#spanend
#spandel
import javax.swing.*;
#spanend
#spandel
import javax.swing.plaf.*;
#spanend
#spanadd
* コメント [#comment]
#spanend
#spanadd
#comment
#spanend
- メモ: [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};
#spandel
public class TranslucentMenuTest {
#spanend
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;
}
#spandel
// @Override public void updateUI() {
#spanend
#spandel
// super.updateUI();
#spanend
#spandel
// if(tree!=null && System.getProperty("java.version").startsWith("1.6.0")) {
#spanend
#spandel
// System.out.println("???: 1.6.0_xx bug??? remake JPopupMenu");
#spanend
#spandel
// tree.setComponentPopupMenu(makePopupMenu());
#spanend
#spandel
// }
#spanend
#spandel
// }
#spanend
private static JPopupMenu makePopupMenu() {
JPopupMenu popup = new TranslucentPopupMenu();
#spandel
//*
#spanend
JMenu menu = new JMenu("Test") {
//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 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();
}
};
#spandel
/*/
#spanend
JMenu menu = new JMenu("Test") {
@Override public JMenuItem add(JMenuItem menuItem) {
menuItem.setOpaque(false);
return super.add(menuItem);
}
@Override public Component add(Component c) {
if(c instanceof JComponent) {
((JComponent)c).setOpaque(false);
}
return super.add(c);
}
};
#spandel
//*/
#spanend
menu.setOpaque(false);
menu.getPopupMenu().setOpaque(false);
#spandel
#spanend
menu.add(new JMenuItem("Undo"));
menu.add(new JMenuItem("Redo"));
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() {
#spandel
// try{
#spanend
#spandel
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
#spanend
#spandel
// }catch(Exception e) {
#spanend
#spandel
// e.printStackTrace();
#spanend
#spandel
// }
#spanend
#spandel
#spanend
PopupFactory.setSharedInstance(new TranslucentPopupFactory());
#spandel
#spanend
JFrame frame = new JFrame("@title@");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new TranslucentMenuTest().makeUI());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#spandel
}
#spanend
#spandel
//http://terai.xrea.jp/Swing/TranslucentPopupMenu.html
#spanend
#spandel
class TranslucentPopupMenu extends JPopupMenu {
#spanend
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;
}
#spandel
// @Override public void updateUI() {
#spanend
#spandel
// super.updateUI();
#spanend
#spandel
// //Test:
#spanend
#spandel
// boolean isNimbus = UIManager.getBorder("PopupMenu.border")==null;
#spanend
#spandel
// if(isNimbus) {
#spanend
#spandel
// //XXX: NimbusLnF not work???
#spanend
#spandel
// setBorder(new BorderUIResource(BorderFactory.createLineBorder(Color.GRAY)));
#spanend
#spandel
// }
#spanend
#spandel
// }
#spanend
@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) {
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)p).setBackground(ALPHA_ZERO);
} else {
System.out.println("Light weight");
}
}
});
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();
}
#spandel
}
#spanend
#spandel
#spanend
#spandel
//
#spanend
#spandel
//<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>
#spanend
#spandel
class TranslucentPopupFactory extends PopupFactory {
#spanend
@Override public Popup getPopup(Component owner, Component contents, int x, int y) throws IllegalArgumentException {
return new TranslucentPopup(owner, contents, x, y);
}
#spandel
}
#spanend
#spandel
#spanend
#spandel
class TranslucentPopup extends Popup {
#spanend
private JWindow popupWindow;
#spandel
#spanend
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);
// determine the popup location
popupWindow.setLocation(ownerX, ownerY);
// add the contents to the popup
popupWindow.getContentPane().add(contents, BorderLayout.CENTER);
contents.invalidate();
JComponent parent = (JComponent) contents.getParent();
// set the shadow border
//parent.setBorder(new ShadowPopupBorder());
}
#spandel
#spanend
@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));
}
#spandel
#spanend
@Override
public void hide() {
this.popupWindow.setVisible(false);
this.popupWindow.removeAll();
this.popupWindow.dispose();
}
#spandel
}
#spanend
#spandel