JDK-7082443 : JComboBox not backward compatible (with Java 6)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 7
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2011-08-23
  • Updated: 2013-04-22
  • Resolved: 2012-02-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u4Fixed 8 b25Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
1.7.0

ADDITIONAL OS VERSION INFORMATION :
Ubuntu 10.10

A DESCRIPTION OF THE PROBLEM :
The JLabels in the dropdown box were opaque in Java 6, but not anymore in Java 7.
(Ubuntu System LaF)

REGRESSION.  Last worked in version 6u26

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
execute this code:


import java.awt.Component;
import javax.swing.*;

public class DebugColorChooser {

    public static void main(String args[]) {

        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println("os: " + System.getProperty("os.name"));
                System.out.println("jvm: " + System.getProperty("java.version"));
                JFrame frame = new JFrame();
                JPanel panel = new JPanel();
                JComboBox jcb = new MyComboBox(new String[]{"Test1", "Test2"});
                panel.add(jcb);
                frame.getContentPane().add(panel);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public static class MyComboBox extends JComboBox {

        public MyComboBox(Object[] items) {
            super(items);
        }

        @Override
        public ListCellRenderer getRenderer() {
            ListCellRenderer dfltRenderer = super.getRenderer();
            return changeRenderer(dfltRenderer);
        }

        private ListCellRenderer changeRenderer(final ListCellRenderer listCellRenderer) {
            if (null != listCellRenderer) {
                ListCellRenderer colorCellRenderer = new ListCellRenderer() {

                    @Override
                    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                        JLabel label = (JLabel) listCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                        System.out.println("opaque: " + label.isOpaque());
                        return label;
                    }
                };
                return colorCellRenderer;
            }
            return null;
        }
    }
}


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
opaque: true
ACTUAL -
opaque: false

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public static class MyComboBox extends JComboBox {

        public MyComboBox(Object[] items) {
            super(items);
        }

        @Override
        public ListCellRenderer getRenderer() {
            ListCellRenderer dfltRenderer = super.getRenderer();
            return changeRenderer(dfltRenderer);
        }

        private ListCellRenderer changeRenderer(final ListCellRenderer listCellRenderer) {
            if (null != listCellRenderer) {
                ListCellRenderer colorCellRenderer = new ListCellRenderer() {

                    @Override
                    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                        JLabel label = (JLabel) listCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                        System.out.println("opaque: " + label.isOpaque());
                        return label;
                    }
                };
                return colorCellRenderer;
            }
            return null;
        }
    }
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
public static class MyComboBox extends JComboBox {

        public MyComboBox(Object[] items) {
            super(items);
        }

        @Override
        public ListCellRenderer getRenderer() {
            ListCellRenderer dfltRenderer = super.getRenderer();
            return changeRenderer(dfltRenderer);
        }

        private ListCellRenderer changeRenderer(final ListCellRenderer listCellRenderer) {
            if (null != listCellRenderer) {
                ListCellRenderer colorCellRenderer = new ListCellRenderer() {

                    @Override
                    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                        JLabel label = (JLabel) listCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                        label.setOpaque(true);
                        return label;
                    }
                };
                return colorCellRenderer;
            }
            return null;
        }
    }

Comments
EVALUATION SynthComboBoxRenderer should have installed Name while constructor is working. The setName invocation (as currently implemented) in the SynthComboBoxRenderer() constructor doesn't work because of the opaque property is installed in the constructor based on the component name (see GTKStyle.isOpaque()). Currently setName tries update style (and defaults as well) but cannot do that, because between SynthComboBoxRenderer and setName style is not changed. As a result the SynthLookAndFeel#updateStyle skips style updating (see line if (newStyle != oldStyle)). The simplest fix is to override the getName, as currently done in the com.sun.java.swing.plaf.gtk.GTKFileChooserUI.FilterComboBoxRenderer#getName method.
15-11-2011