views:

174

answers:

1

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?

+1  A: 

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).

Devon_C_Miller