Morinar
Morinar

Reputation: 3550

Why is a JLabel in a JPopupMenu not respecting its Look and Feel?

I have a Java application with a custom defined Look and Feel in which the user can switch between a light and a dark mode. One of the things we have is a right click popup menu that inherits from the JPopupMenu class. The first thing we add to the menu is a JLabel:

add( new JLabel( "<html><i> " + field.desc + "</i><br/>field = " + field.getName() + "</html>" ) );

Now, we have altered the L&F for JLabels and they appear in quite a few places in the app styles correctly. We have modified:

Label.background
Label.foreground

Additionally, the L&F for the MenuItems has also been modified via:

PopupMenu.border
PopupMenu.foreground
PopupMenu.background

For what it's worth, we've also modified similar properties on MenuItems.

The problem is that that label that occurs inside the popup menu doesn't seem to be respecting the background color. The foreground color changes when switching between light and dark mode, but the background color does not. I did a screen grab and eyedropped the color that the background color was set to and couldn't find a match anywhere in our L&F settings, which would seem to suggest that it was just using the default L&F (Windows probably) on it.

Is this perhaps a bug? Or am I not setting some L&F property I should be? I couldn't seem to find anybody in the Google-sphere with the same problem, so any help would be appreciated.

Upvotes: 1

Views: 1237

Answers (2)

joseluisbz
joseluisbz

Reputation: 1648

  public static void changeLaf(JComponent component, String laf) {
    try {
      UIManager.setLookAndFeel(laf);
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
    }

    SwingUtilities.updateComponentTreeUI(component);
  }

How to use it?

changeLaf(/*your JPopupMenu*/, /*your ClassName laf*/);

Here

    JPopupMenu pmLAF = new JPopupMenu();
    JMenuItem miRandomColor = new JMenuItem("Set Random Color");
    JMenuItem miWhiteColor = new JMenuItem("Set White Color");
    JMenuItem miDefaultColor = new JMenuItem("Set Default Color");
    pmLAF.add(miRandomColor);
    pmLAF.add(miWhiteColor);
    pmLAF.addSeparator();
    pmLAF.add(miDefaultColor);

    JLabel lblMetal = new JLabel(" Metal ");
    lblMetal.setBorder(BorderFactory.createEtchedBorder());
    JLabel lblMotif = new JLabel(" Motif ");
    lblMotif.setBorder(BorderFactory.createEtchedBorder());
    JLabel lblNimbus = new JLabel("  Nimbus ");
    lblNimbus.setBorder(BorderFactory.createEtchedBorder());

I put LAF fixed for Labels and Changeable for JPopupMenu

            changeLaf(pmLAF, /*Change LAF String*/);
            changeLaf(lblMetal, "javax.swing.plaf.metal.MetalLookAndFeel");
            changeLaf(lblMotif, "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
            changeLaf(lblNimbus, "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");

Windows LAF

Windows Theme

Nimbus LAF

enter image description here

Motif LAF

enter image description here

Metal LAF

enter image description here

Some ClassName

/*
#  --laf javax.swing.plaf.mac.MacLookAndFeel
#  --laf apple.laf.AquaLookAndFeel
#  --laf com.apple.laf.AquaLookAndFeel
#  --laf com.sun.java.swing.plaf.gtk.GTKLookAndFeel
#  --laf com.sun.java.swing.plaf.motif.MotifLookAndFeel
#  --laf com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
#  --laf com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel
#  --laf com.sun.java.swing.plaf.windows.WindowsLookAndFeel
#  --laf javax.swing.plaf.basic.BasicLookAndFeel
#  --laf javax.swing.plaf.metal.MetalLookAndFeel
#  --laf javax.swing.plaf.multi.MultiLookAndFeel
#  --laf javax.swing.plaf.synth.SynthLookAndFeel
#  --laf javax.swing.plaf.nimbus.NimbusLookAndFeel
#  --laf it.unitn.ing.swing.plaf.macos.MacOSLookAndFeel
*/

Upvotes: 0

Morinar
Morinar

Reputation: 3550

I should have known that this would be the answer: the JLabel was set to transparent so it's background wasn't being respected. Altering the code like this fixed the problem real nice:

JLabel fieldInfo = new JLabel( "<html><i> " + field.desc + "</i><br/>field = " + field.getName() + "</html>" );
fieldInfo.setOpaque( true );

Upvotes: 2

Related Questions