Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8041559

getTableCellRendererComponent called with Object = null with access bridge

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 7, 8u5
    • client-libs

      FULL PRODUCT VERSION :
      jre6u21, jre7u45

      ADDITIONAL OS VERSION INFORMATION :
      Windows XP,, Windows 8.1

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      java access bridge must be enabled in accessibility.properties

      A DESCRIPTION OF THE PROBLEM :
      When java access bridge is enabled, the getTableCellRendererComponent is often called with a null reference to the object to render. Without java acccess bridge enabled, everything works fine.

      ADDITIONAL REGRESSION INFORMATION:
      jre7u45

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run IncellEditDemo.jar and select the JComboboxess in the second column. The stdout shows the parameter of the call to getTableCellRendererComponent and getTableCellEditorComponent.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      RENDER: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "0: item 2", at: (0, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      EDIT: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      ACTUAL -
      ENDER: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "null", at: (0, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "null", at: (0, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "null", at: (1, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "0: item 0", at: (0, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "null", at: (1, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "null", at: (2, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "1: item 0", at: (1, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "3: item 0", at: (3, 1); isSelected: false
      RENDER: passed value is: "null", at: (2, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "null", at: (3, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "2: item 0", at: (2, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "6: item 0", at: (6, 1); isSelected: false
      EDIT: passed value is: "4: item 0", at: (4, 1); isSelected: false
      RENDER: passed value is: "null", at: (3, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "null", at: (4, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "3: item 0", at: (3, 1); isSelected: false
      EDIT: passed value is: "5: item 0", at: (5, 1); isSelected: false
      RENDER: passed value is: "null", at: (4, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "null", at: (5, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "4: item 0", at: (4, 1); isSelected: false
      EDIT: passed value is: "6: item 0", at: (6, 1); isSelected: false
      RENDER: passed value is: "null", at: (5, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "null", at: (6, 1); isSelected: false
      RENDER: returning <null>
      RENDER: passed value is: "5: item 0", at: (5, 1); isSelected: false

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package InCellEditDemo;

      import java.awt.BorderLayout;
      import java.awt.Component;
      import java.awt.GridBagConstraints;
      import java.awt.GridBagLayout;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.event.WindowEvent;
      import java.awt.event.WindowListener;
      import javax.accessibility.AccessibleContext;
      import static javax.swing.BorderFactory.createTitledBorder;
      import javax.swing.DefaultCellEditor;
      import javax.swing.JButton;
      import javax.swing.JComboBox;
      import javax.swing.JPanel;
      import javax.swing.JFrame;
      import javax.swing.JTable;
      import javax.swing.SwingUtilities;
      import javax.swing.table.DefaultTableCellRenderer;
      import javax.swing.table.DefaultTableModel;
      import javax.swing.table.TableColumn;

      /**
       *
       */
      public class InCellEditView extends JFrame
       implements ActionListener, WindowListener {

        /**
         *
         */
        @SuppressWarnings("LeakingThisInConstructor")
        public InCellEditView()
        {
          setTitle("Testapplikation In-Cell Edit in Tabellen");
          addWindowListener(this);
        }

        /**
         * Set accessibility info of context
         *
         * @param context
         * @param name
         * @param desc
         */
        private void _setAccessibilityInfo(AccessibleContext context,
         String name, String desc)
        {
          context.setAccessibleName(name);
          context.setAccessibleDescription(desc);
        }

        /**
         * Exit application
         *
         * @param e
         */
        private void _handleOKButton(ActionEvent e)
        {
          System.exit(0);
        }

        /**
         * Handle button action
         *
         * @param e
         */
        @Override
        public void actionPerformed(ActionEvent e)
        {
          String action = e.getActionCommand();
          switch (action) {
          case "Exit":
            _handleOKButton(e);
            break;
          default:
            break;
          }
        }

        /**
         *
         */
        private void _setupLayout()
        {
          JPanel panel = new JPanel(new GridBagLayout());

          JButton exitButton = new JButton("Exit");
          exitButton.addActionListener(this);
          _setAccessibilityInfo(exitButton.getAccessibleContext(), "Exit",
           "With this button you will leave the applikation");

          // Table view panel
          JPanel tableViewPanel = new JPanel(new BorderLayout());
          tableViewPanel.setBorder(createTitledBorder("Table view panel"));
          JTable t = _createTable();
          tableViewPanel.add(t.getTableHeader(), BorderLayout.PAGE_START);
          tableViewPanel.add(t, BorderLayout.CENTER);

          // Control panel
          JPanel controlPanel = new JPanel(new GridBagLayout());
          controlPanel.setBorder(createTitledBorder("Control panel"));

          GridBagConstraints c = new GridBagConstraints();
          c.gridy = 0;
          c.gridx = 0;
          c.gridwidth = 2;
          c.insets.top = 0;
          c.insets.left = 0;
          c.anchor = GridBagConstraints.CENTER;
          c.fill = GridBagConstraints.NONE;
          controlPanel.add(exitButton, c);

          // Layout panel
          c.insets.bottom = 0;
          c.insets.top = 0;
          c.insets.left = 0;
          c.insets.right = 0;
          c.gridx = 0;
          c.gridy = 0;
          c.anchor = GridBagConstraints.NORTHWEST;
          c.fill = GridBagConstraints.BOTH;
          c.weightx = 1.0;
          c.weighty = 1.0;
          panel.add(tableViewPanel, c);
          c.gridy++;
          panel.add(controlPanel, c);
          add(panel);
          pack();
        }

        public class MyTableModel extends DefaultTableModel {
          private static final int NUM_COLUMNS = 2;
          public int COL_ROWID = 0;
          public int COL_ENUM = 1;
          private final Object[][] _data;
          private final Object[] _headers;

          public MyTableModel(int rows)
          {
            super(rows, NUM_COLUMNS);

            _headers = new Object[NUM_COLUMNS];
            _headers[COL_ROWID] = "Row";
            _headers[COL_ENUM] = "Enum";
            setColumnIdentifiers(_headers);

            _data = new Object[NUM_COLUMNS][rows];
            for (int j = 0; j < rows; j++) {
              String[] items = new String[rows];

              for (int i = 0; i < rows; i++) {
                items[i] = (j + ": item " + i);
              }

              _data[0][j] = j;
              _data[COL_ENUM][j] = new JComboBox<>(items);
            }
          }

          @Override
          public Object getValueAt(int row, int col)
          {
            if ((row >= 0) && (row < getRowCount()) && (col >= 0) && (col
             < getColumnCount())) {
              if (col == COL_ENUM) {
                return ((JComboBox) _data[col][row]).getSelectedItem();
              }
              else {
                return _data[col][row];
              }
            }
            return null;
          }

          public Object getDataAt(int row, int col)
          {
            if ((row >= 0) && (row < getRowCount()) && (col >= 0) && (col
             < getColumnCount())) {
              return _data[col][row];
            }
            return null;
          }
        };

        public class MyComboRenderer extends DefaultTableCellRenderer {
          public MyComboRenderer()
          {
            super();
          }

          @Override
          public Component getTableCellRendererComponent(JTable table, Object value,
           boolean isSelected, boolean hasFocus, int row, int column)
          {
            System.out.println("RENDER: passed value is: \"" + value + "\", at: ("
             + row + ", " + column + "); isSelected: " + isSelected);

            if (value == null) {
              System.out.println("RENDER: returning <null>");
              return null;
            }
            return super.getTableCellRendererComponent(table, value, isSelected,
             hasFocus, row, column);
          }
        }

        public class MyComboEditor extends DefaultCellEditor {
          private final MyTableModel _m;

          public MyComboEditor(MyTableModel m)
          {
            super(new JComboBox());
            _m = m;
          }

          @Override
          public Component getTableCellEditorComponent(JTable table, Object value,
           boolean isSelected, int row, int column)
          {
            System.out.println("EDIT: passed value is: \"" + value + "\", at: (" + row
             + ", " + column + "); isSelected: " + isSelected);
            if (value == null) {
              System.out.println("EDIT: returning <null>");
              return null;
            }
            if (column == _m.COL_ENUM) {
              return (JComboBox) _m.getDataAt(row, column);
            }
            return super.getTableCellEditorComponent(table, value, isSelected,
             row, column);
          }
        };

        private JTable _createTable()
        {
          MyTableModel m = new MyTableModel(7);
          JTable table = new JTable(m) {
            @Override
            public boolean isCellEditable(int row, int column)
            {
              return column == ((MyTableModel) getModel()).COL_ENUM;
            }
          };
          TableColumn tc = table.getColumnModel().getColumn(m.COL_ENUM);

          tc.setPreferredWidth(70);
          tc.setCellRenderer(new MyComboRenderer());
          tc.setCellEditor(new MyComboEditor(m));

          table.setRowHeight(22);
          table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);

          table.setShowGrid(true);

          return table;
        }

        @Override
        public void windowOpened(WindowEvent e)
        {
        }

        @Override
        public void windowClosing(WindowEvent e)
        {
          dispose();
        }

        @Override
        public void windowClosed(WindowEvent e)
        {
          System.exit(0);
        }

        @Override
        public void windowIconified(WindowEvent e)
        {
        }

        @Override
        public void windowDeiconified(WindowEvent e)
        {
        }

        @Override
        public void windowActivated(WindowEvent e)
        {
        }

        @Override
        public void windowDeactivated(WindowEvent e)
        {
        }

        /**
         *
         * @param args
         */
        public static void main(String[] args)
        {
          SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run()
            {
              InCellEditView view = new InCellEditView();
              view._setupLayout();
              view.setVisible(true);
            }
          });
        }
      }

      ---------- END SOURCE ----------

            abhiscxk Abhishek Kumar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: