Нимбус часто выглядит великолепно, но для определенных комбинаций цветов результат неоптимальный. В моем случае фон JPopupMenu не подходит, поэтому я хочу установить его вручную.
Я на Java 7, и, что интересно, Nimbus полностью игнорирует настройку некоторых свойств в UIManager (например, PopupMenu.background). Поэтому мой единственный вариант - создать подкласс JPopupMenu, который переопределяет paintComponent(...). Я знаю, что это противно, но, по крайней мере, это сработало.
Однако, если вы добавите JMenu в другое меню, он введет в него собственный экземпляр JPopupMenu, и я не мог понять, как заменить его своим собственным подклассом.
Даже присвоение встроенного экземпляра PopupMenuUI не принесло никаких результатов. Если унаследовано непосредственно из JPopupMenu, был вызван метод overriden paint(...), но неважно, что я сделал, ничего не было нарисовано. Если унаследовано от javax.swing.plaf.synth.SynthPopupMenuUI paint, даже не вызывается, и результат получается, если я вообще не установил собственный PopupMenuUI.
Итак, простой вопрос: как отрегулировать цвет фона одного JPopupMenu или (если это проще) все из них на Java 7 с помощью Nimbus как 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) перед установкой L & F, но для меня это не приносит никаких результатов (что означает: никаких изменений в цветах по умолчанию вообще не происходит). Приведенный выше код, по крайней мере, приносит:

То же самое (что означает ничего) происходит, если вы используете JPopupMenu.setBackground(...). Это связано с тем, что в Nimbus используется внутренний художник, который вычисляет цвет из основных цветов Nimbus и игнорирует свойство компонентов. В этом примере вы можете использовать следующее в качестве обходного пути:
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 не приводит к каким-либо результатам, так как JMenu, похоже, обращается к нему, включив экземпляр JPopupMenu без использования getter.
