Нимбус часто выглядит великолепно, но для определенных комбинаций цветов результат неоптимальный. В моем случае фон 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.