Swing and Nimbus :Заменить фон JPopupMenu (, прикрепленный к JMenu)

Nimbus часто выглядит великолепно, но для некоторых цветовых комбинаций результат -не оптимален. В моем случае фон из JPopupMenuне подходит, поэтому я хочу установить его вручную.

Я на Java 7 и, что интересно, Nimbus полностью игнорирует настройку некоторых свойств вUIManager(нравитсяPopupMenu.background). Поэтому моим единственным вариантом было создать подкласс JPopupMenu, который переопределяет paintComponent(...). Я знаю, это противно, но, по крайней мере, это сработало.

Однако, если вы добавите JMenuв другое меню, оно встроит свой собственный экземпляр JPopupMenu, и я не мог понять, как заменить его своим собственным подклассом.

Даже присвоение встроенному экземпляру собственного PopupMenuUIне дало никаких результатов. Если он унаследован непосредственно от JPopupMenu, вызывался переопределенный метод paint(...), но, что бы я ни делал, ничего не рисовалось. Если унаследовано отjavax.swing.plaf.synth.SynthPopupMenuUIpaintдаже не вызывается, и в результате я вообще не установил собственный 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, но для меня это не дает никаких результатов (означает :вообще никаких изменений в цветах по умолчанию ). Код выше, по крайней мере, приносит:

First screenshot

То же самое (означает, что ничего )не произойдет, если вы используете 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());
    }
};

Что приносит

SecondScreen

Однако этот обходной путь не работает, если вы вставляете JMenu, который сам является оболочкой JPopupMenu, которую вы не можете переопределить :

JMenu jmenu = new JMenu("D");
jmenu.add(new JMenuItem("E"));
menu.add(jmenu);

. дает, как и ожидалось:

Third screen

Вы можете получить этот JPopupMenuс помощью JMenu.getPopupMenu(), но вы не можете установить его. Даже переопределение этого метода в собственном подклассе JMenuне дает никаких результатов, поскольку JMenu, похоже, обращается к своему обернутому экземпляру JPopupMenuбез использования геттера.

15
задан Rob 9 April 2013 в 16:34
поделиться