JDK-6581349 : Call to setBorder in JTable produces strange focus behavious
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-07-17
  • Updated: 2011-04-28
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
Both Java 1.6u2, and Java 5

ADDITIONAL OS VERSION INFORMATION :
Windows XP

A DESCRIPTION OF THE PROBLEM :
I was trying to provide a visual highlighting for the currently selected component by setting a border around it. This works fine for almost every example, however, when used in conjunction with an editable table, it wil produce pretty strange results. If you try to edit the table row in the attached example, the cell editor will receive the focus for a split second and lose it right afterwards as the table magically seems to request the focus itself.

The funny thing about the example: You can remove the focusGained call OR the focusLost call and it will work as expected, just in conjunction it won't work.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try to run the attached example program.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would have expected the table to lose its 'focus border' when the keyboard focus moves to the cell editor
ACTUAL -
The CellEditor receives the focus, but then immediately loses it as the focus goes back to the table. This is definitely triggered by the call to setBorder, if you comment any of the two out it will work like expected.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final JPanel panel = new JPanel(new GridLayout(1,1));
                final JTable table = new JTable(new Object[][]{{"Foo","Bar"}}, new Object[]{"Foo","Bar"});
                table.setFillsViewportHeight(true);
                table.addFocusListener(new FocusListener() {
                    public void focusGained(FocusEvent e) {
                        System.out.println("Gained: "+e.getSource());
                        /* You could also do this using invokeLater, doesn't matter */
                        panel.setBorder(BorderFactory.createRaisedBevelBorder());
                    }

                    public void focusLost(FocusEvent e) {
                        System.out.println("Lost: "+e.getSource());
                        /* You could also do this using invokeLater, doesn't matter */
                        panel.setBorder(null);
                    }
                });
                panel.add(new JScrollPane(table));


                final JFrame frame = new JFrame();
                frame.setSize(400,400);
                frame.setLocationRelativeTo(null);
                frame.setContentPane(panel);
                frame.setVisible(true);
            }
        });
    }
---------- END SOURCE ----------

Comments
EVALUATION When focusLost() unsets the border, the panel is revalidated and the table inside it gets more space. So the columns are resized, and editing is canceled (see JTable.columnMarginChanged()). To fix this you may want to use an empty border with the same margins as the "focused" border. This way when borders change, no revalidating will happen, because border insets will be the same.
24-05-2010

EVALUATION This may be connected with 6568959
30-10-2007