title: Swing and Nimbus: Replace background of JPopupMenu (attached to JMenu)
body: <p>Nimbus often looks great, but for certain color combinations the result is non-optimal. In my case, the background of a <code>JPopupMenu</code> does not fit, which is why I want to set it manually.</p>
  
  <p>I'm on Java 7 and, interestingly, Nimbus fully ignores the setting of some properties in the <code>UIManager</code> (like <code>PopupMenu.background</code>). So my only option was to create a subclass of <code>JPopupMenu</code> that overrides <code>paintComponent(...)</code>. I know, that's nasty, but at least it worked.</p>
  
  <p>However, if you add a <code>JMenu</code> to another menu, it embeds it's own instance of <code>JPopupMenu</code> and I could not figure out how to replace it with my own subclass.</p>
  
  <p>Even assigning an own <code>PopupMenuUI</code> to the embedded instance didn't bring any results. If inherited directly from <code>JPopupMenu</code> the overriden <code>paint(...)</code> method was called, but, not matter what I did, nothing was drawn. If inherited from <code>javax.swing.plaf.synth.SynthPopupMenuUI</code> <code>paint</code> isn't even called and the result is if I hadn't set an own <code>PopupMenuUI</code> at all. </p>
  
  <p>So the simple question is: How do I adjust the background color of one <code>JPopupMenu</code> or (if that's easier) all of them on Java 7 using Nimbus as L&amp;F?</p>
  
  <p><strong>Edit: Code example</strong></p>
  
  <p>Take a look at the following code and the result:</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>I know, some say that you should use <code>UIManager.put(key, value)</code> or <code>UIManager.getLookAndFeelDefautls().put(key,value)</code> <em>before</em> setting the L&amp;F, but for me this does not bring any results (meaning: no changes to the default colors at all). The code above at least brings:</p>
  
  <p><img src="https://i.stack.imgur.com/I7GpX.png" alt="First screenshot"></p>
  
  <p>Same thing (meaning nothing) happens if you use <code>JPopupMenu.setBackground(...)</code>. This is because Nimbus uses an internal painter, which computes the color from Nimbus' primary colors and ignores the components' property. In this example, you can use the following as workaround:</p>
  
  <pre><code>JPopupMenu menu = new JPopupMenu() {
      @Override
      public void paintComponent(final Graphics g) {
          g.setColor(Color.GREEN);
          g.fillRect(0,0,getWidth(), getHeight());
      }
  };
  </code></pre>
  
  <p>Which brings</p>
  
  <p><img src="https://i.stack.imgur.com/JJFug.png" alt="SecondScreen"></p>
  
  <p>However, this workaround does not work if you insert a <code>JMenu</code> which itself wraps a <code>JPopupMenu</code> you can't override:</p>
  
  <pre><code>JMenu jmenu = new JMenu("D");
  jmenu.add(new JMenuItem("E"));
  menu.add(jmenu);
  </code></pre>
  
  <p>gives, as expected:</p>
  
  <p><img src="https://i.stack.imgur.com/56PNg.png" alt="Third screen"></p>
  
  <p>You can retrieve this <code>JPopupMenu</code> using <code>JMenu.getPopupMenu()</code> but you can't set it. Even overriding this method in an own subclass of <code>JMenu</code> does not bring any results, as <code>JMenu</code> seems to access it's enwrapped instance of <code>JPopupMenu</code> without using the getter.</p>