问题背景
现在要使JPopupMenu
背景完全透明,并且我想自定义它的背景,并且不影响它的菜单项的样式
解决过程
首先看到这个需求,按照基本思路是重写JPopupMenu
类,重写paintComponent
方法画一个背景。但是JPopupMenu
与其他组件的自定义方法不同,它没有我们想象地那么简单,它是基于Window
类的一个重量级组件,你会发现,即便是重写了该方法,并且什么也不做,依旧会有一个灰色的背景!并且setOpaque(false)
依旧无效!
@Override
protected void paintComponent(Graphics g) {
// 什么也不画
}
解决问题的根本在于想办法JPopupMenu
类对应的Window
完全透明,首先我们得设置它为重量级弹出以使用Window
setDefaultLightWeightPopupEnabled(false);
然后重写setVisible
方法,SwingUtilities.getWindowAncestor(this)
获取对应的Window
对象,然后AWTUtilities.setWindowOpaque(w, false);
使该Window
对象的背景透明即可,完美解决!
@Override
public void setVisible(boolean b) {
if (b == isVisible())
return;
super.setVisible(b);
if (b) {
// attempt to set tranparency
try {
Window w = SwingUtilities.getWindowAncestor(this);
AWTUtilities.setWindowOpaque(w, false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意: 有人可能会问为什么不用setOpacity
来设置Window
透明度,是因为这个方法设置的是整个窗口以及子组件的透明度,意味着你设置为0之后整个JPopupMenu
就看不到了,而setWindowOpaque
仅仅是让Swing不去画窗口的背景!