Swing 和 Nimbus:替换 JPopupMenu 的背景(附加到 JMenu)
Nimbus通常看起来很棒,但对于某些颜色组合,结果是非最佳的。在我的情况下,a的背景不适合,这就是为什么我想手动设置它。JPopupMenu
我在Java 7上,有趣的是,Nimbus完全忽略了(如)中某些属性的设置。因此,我唯一的选择是创建一个覆盖的子类。我知道,这很讨厌,但至少它有效。UIManager
PopupMenu.background
JPopupMenu
paintComponent(...)
但是,如果您将一个添加到另一个菜单,它会嵌入它自己的实例,我无法弄清楚如何用我自己的子类替换它。JMenu
JPopupMenu
即使为嵌入式实例分配一个 own 也没有带来任何结果。如果直接从重写的方法被调用,但是,无论我做什么,都没有绘制任何内容。如果继承自甚至没有被调用,结果是如果我根本没有设置一个自己。PopupMenuUI
JPopupMenu
paint(...)
javax.swing.plaf.synth.SynthPopupMenuUI
paint
PopupMenuUI
所以简单的问题是:如何在Java 7上使用Nimbus作为L&F来调整一个或(如果更容易的话)所有背景的颜色?JPopupMenu
编辑:代码示例
请看下面的代码和结果:
public static void main(final String[] args) {
try {
UIManager.setLookAndFeel(NimbusLookAndFeel.class.getCanonicalName());
UIManager.getLookAndFeelDefaults().put("PopupMenu.background", Color.GREEN);
UIManager.getLookAndFeelDefaults().put("Panel.background", Color.RED);
UIManager.getLookAndFeelDefaults().put("List.background", Color.BLUE);
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
JList list = new JList();
panel.add(list);
frame.getContentPane().add(panel);
JPopupMenu menu = new JPopupMenu();
menu.add(new JMenuItem("A"));
menu.add(new JMenuItem("B"));
menu.add(new JMenuItem("C"));
frame.setVisible(true);
menu.show(frame, 50, 50);
}
我知道,有些人说你应该在设置L&F之前使用或,但对我来说,这不会带来任何结果(意思是:完全没有改变默认颜色)。上面的代码至少带来了:UIManager.put(key, value)
UIManager.getLookAndFeelDefautls().put(key,value)
如果您使用 ,则会发生同样的事情(意味着什么都不发生)。这是因为 Nimbus 使用内部画家,它根据 Nimbus 的原色计算颜色并忽略组件的属性。在此示例中,您可以使用以下方法作为解决方法:JPopupMenu.setBackground(...)
JPopupMenu menu = new JPopupMenu() {
@Override
public void paintComponent(final Graphics g) {
g.setColor(Color.GREEN);
g.fillRect(0,0,getWidth(), getHeight());
}
};
这就带来了
但是,如果您插入一个本身包装了一个您无法覆盖的,则此解决方法不起作用:JMenu
JPopupMenu
JMenu jmenu = new JMenu("D");
jmenu.add(new JMenuItem("E"));
menu.add(jmenu);
正如预期的那样,
您可以使用 检索此内容,但无法对其进行设置。即使在自己的子类中重写此方法也不会带来任何结果,因为似乎在不使用 getter 的情况下访问它的封装实例。JPopupMenu
JMenu.getPopupMenu()
JMenu
JMenu
JPopupMenu