Nimbus通常看起来很棒,但对于某些颜色组合,结果并非最佳。在我的情况下,JPopupMenu
的背景不合适,这就是我想手动设置的原因。
我使用的是Java 7,有趣的是,Nimbus完全忽略了UIManager
中某些属性的设置(如PopupMenu.background
)。所以我唯一的选择是创建一个覆盖JPopupMenu
的{{1}}子类。我知道,这很讨厌,但至少它起作用了。
但是,如果你将paintComponent(...)
添加到另一个菜单,它会嵌入它自己的JMenu
实例,我无法弄清楚如何用我自己的子类替换它。
即使为嵌入式实例分配自己的JPopupMenu
也没有带来任何结果。如果直接从PopupMenuUI
继承,则会调用overriden JPopupMenu
方法,但是,无论我做了什么,都没有绘制任何内容。如果甚至没有调用继承自paint(...)
javax.swing.plaf.synth.SynthPopupMenuUI
的结果,那么结果就是我根本没有设置自己的paint
。
所以简单的问题是:如何使用Nimbus作为L& F来调整Java 7上的PopupMenuUI
或(如果更容易)所有这些的背景颜色?
编辑:代码示例
查看以下代码和结果:
JPopupMenu
我知道,有人说你应该在设置L& F之前使用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);
}
或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);
检索此JPopupMenu
,但无法进行设置。即使在JMenu.getPopupMenu()
的子类中重写此方法也不会产生任何结果,因为JMenu
似乎在不使用getter的情况下访问了JMenu
的包装实例。
答案 0 :(得分:8)
一种方法是为各个JMenuItems的背景着色并使它们不透明:
JMenuItem a = new JMenuItem("A");
a.setOpaque(true);
a.setBackground(Color.GREEN);
然后给菜单本身一个绿色边框以填补其余部分:
menu.setBorder(BorderFactory.createLineBorder(Color.GREEN));
可能有一种简单/更直接的方式,但这对我有用。
答案 1 :(得分:8)
两个答案都有一些错误
以及上面提到的覆盖大多数影响另一个JComponents及其颜色的UIDeafault的方法
Nimbus拥有自己的Painter,就是一个例子......
来自代码
import com.sun.java.swing.Painter;
import java.awt.*;
import javax.swing.*;
public class MyPopupWithNimbus {
public MyPopupWithNimbus() {
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"));
JMenu jmenu = new JMenu("D");
jmenu.add(new JMenuItem("E"));
menu.add(jmenu);
frame.setVisible(true);
menu.show(frame, 50, 50);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
UIManager.getLookAndFeelDefaults().put("PopupMenu[Enabled].backgroundPainter",
new FillPainter(new Color(127, 255, 191)));
}
}
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MyPopupWithNimbus aa = new MyPopupWithNimbus();
}
});
}
}
class FillPainter implements Painter<JComponent> {
private final Color color;
FillPainter(Color c) {
color = c;
}
@Override
public void paint(Graphics2D g, JComponent object, int width, int height) {
g.setColor(color);
g.fillRect(0, 0, width - 1, height - 1);
}
}
答案 2 :(得分:7)
不是整个故事 - 但看起来将菜单/项目的不透明度设置为true部分解决了它(正如@Derek Richard已经为在完全应用程序控制下创建的项目所做的那样):
UIDefaults ui = UIManager.getLookAndFeelDefaults();
ui.put("PopupMenu.background", GREEN);
ui.put("Menu.background", GREEN);
ui.put("Menu.opaque", true);
ui.put("MenuItem.background", GREEN);
ui.put("MenuItem.opaque", true);
等等,适用于所有类型的项目,如radioButton / checkBox。
这仍留下上/下灰色区域 - 不知道哪个部分负责该绘图。删除保证金有助于降低价格
// this looks not so good, but without the margins above/below are still grey
ui.put("PopupMenu.contentMargins", null);
教程中有一个list of property keys。