3

I'm currently trying to write a custom ListCellRenderer for a JList. Unfortunately, nearly all examples simply use DefaultListCellRenderer as a JLabel and be done with it; I needed a JPanel, however (since I need to display a little more info than just an icon and one line of text).

Now I have a problem with the background colors, specifically with the Nimbus PLAF. Seemingly the background color I get from list.getBackground() is white, but paints as a shade of gray (or blueish gray). Outputting the color I get yields the following:

Background color: DerivedColor(color=255,255,255 parent=nimbusLightBackground offsets=0.0,0.0,0.0,0 pColor=255,255,255

However, as can be seen, this isn't what gets painted.

alt text

It obviously works fine for the selected item. Currently I even have every component I put into the JPanel the cell renderer returns set to opaque and with the correct foreground and background colors—to no avail.

Any ideas what I'm doing wrong here?

ETA: Example code which hopefully runs.

public class ParameterListCellRenderer implements ListCellRenderer {
  @Override
  public Component getListCellRendererComponent(JList list, Object value,
      int index, boolean isSelected, boolean cellHasFocus) {
    // some values we need
    Border border = null;
    Color foreground, background;
    if (isSelected) {
      background = list.getSelectionBackground();
      foreground = list.getSelectionForeground();
    } else {
      background = list.getBackground();
      foreground = list.getForeground();
    }
    if (cellHasFocus) {
      if (isSelected) {
        border = UIManager.getBorder("List.focusSelectedCellHighlightBorder");
      }
      if (border == null) {
        border = UIManager.getBorder("List.focusCellHighlightBorder");
      }
    } else {
      border = UIManager.getBorder("List.cellNoFocusBorder");
    }

    System.out.println("Background color: " + background.toString());

    JPanel outerPanel = new JPanel(new BorderLayout());
    setProperties(outerPanel, foreground, background);
    outerPanel.setBorder(border);

    JLabel nameLabel = new JLabel("Factory name here");
    setProperties(nameLabel, foreground, background);
    outerPanel.add(nameLabel, BorderLayout.PAGE_START);

    Box innerPanel = new Box(BoxLayout.PAGE_AXIS);
    setProperties(innerPanel, foreground, background);
    innerPanel.setAlignmentX(Box.LEFT_ALIGNMENT);
    innerPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));

    JLabel label = new JLabel("param: value");

    label.setFont(label.getFont().deriveFont(
        AffineTransform.getScaleInstance(0.95, 0.95)));
    setProperties(label, foreground, background);

    innerPanel.add(label);

    outerPanel.add(innerPanel, BorderLayout.CENTER);

    return outerPanel;
  }

  private void setProperties(JComponent component, Color foreground,
      Color background) {
    component.setOpaque(true);
    component.setForeground(foreground);
    component.setBackground(background);
  }
}

The weird thing is, if I do

if (isSelected) {
  background = new Color(list.getSelectionBackground().getRGB());
  foreground = new Color(list.getSelectionForeground().getRGB());
} else {
  background = new Color(list.getBackground().getRGB());
  foreground = new Color(list.getForeground().getRGB());
}

it magically works. So maybe the DerivedColor with nimbusLightBackground I'm getting there may have trouble?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Joey
  • 344,408
  • 85
  • 689
  • 683
  • It looks as if the containted JLabels would paint their own background. Guess you are getting the same result when you set their `opaque` to `false`? I think in that case we will need some example code to reproduce... – Peter Lang May 07 '10 at 10:26
  • @Peter: Added code and another curiosity. Hope I got each part of the code that depends on our code here. – Joey May 07 '10 at 10:46
  • While I can perfectly reproduce your problem and your workaround, I can't explain it. This forum thread talks about Nimbus ignoring `UIResource` (your background-color is a `DerivedColor$UIResource`), so this could be related. Not sure though :) – Peter Lang May 07 '10 at 14:09
  • @Peter: Ok, I think this question leads a little into the wrong direction anyway. At least the only answer I got seems to be about how to specifically cater for the Nimbus LAF. I think the whole point of the PLAF system was that you can swap looks easily so I was more on the lookout for a good, sensible way of implementing a ListCellRenderer. Sadly, even a tutorial by one of the Swing developers makes flawed assumptions and ignores things. – Joey May 07 '10 at 20:23

1 Answers1

3

JPanels default to opaque=true while jLabels default to opaque=false.

So, when a DefaultCellRender uses a JLabel, it gets the background of its parent.

Try just setting opaque to false on your panel.

Update:

Nimbus is using its own custom ListCellRenderer. I've found 2 mentions of working around it, one here on SO and one in Google's code repository (look for UpdateUI and NimbusCellRenderer).

Community
  • 1
  • 1
Devon_C_Miller
  • 16,248
  • 3
  • 45
  • 71