-
Bug
-
Resolution: Unresolved
-
P3
-
None
-
6
-
x86
-
linux
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-b105, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux primus 2.6.16.27-0.9-default #1 Tue Feb 13 09:35:18 UTC 2007 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
When deleting the last row of a table, the redraw/validate causes the entire table to be redrawn, not just the visible part. For tables with many rows, read from a DB or other persistent storage, this results in long UI delays (e.g. 15 secs for a 3'000 row table).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the code. It will print "getValueAt(n,0)" for the first twenty rows or so. Scroll to the end of table. This will print "getValueAt(n,0)" for the remaining ~980 rows.
Now press the delete button.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After deleting the last row, getValueAt() should only be called for one or two rows, or maybe twenty if there is no backing image store to scroll.
ACTUAL -
After deleting the last row, getValueAt() is called for all 1000 rows.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class RowDeleteBug extends JFrame {
private RowDeleteTableModel tableModel;
public RowDeleteBug() {
super("RowDeleteBug");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
JTable table = new JTable(tableModel = new RowDeleteTableModel(1000));
getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
JButton button = new JButton("Delete");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tableModel.deleteRow();
}
});
getContentPane().add(button, BorderLayout.SOUTH);
setSize(400, 400);
}
public static void main(String[] args) {
new RowDeleteBug().setVisible(true);
}
}
class RowDeleteTableModel extends AbstractTableModel {
private int rowCount;
RowDeleteTableModel(int initialRowCount) { rowCount = initialRowCount; }
public int getRowCount() { return rowCount; }
public int getColumnCount() { return 1; }
public Object getValueAt(int row, int col) {
System.out.println("getValueAt(" + row + "," + col + ")");
return "Item #" + row;
}
void deleteRow() {
rowCount--; fireTableRowsDeleted(rowCount, rowCount);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Overriding the table's getRowAtPoint() method to not return -1, but getRowCount() - 1 if the y coordinate exceeds the real table height, causes the bug to disappear.
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-b105, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux primus 2.6.16.27-0.9-default #1 Tue Feb 13 09:35:18 UTC 2007 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
When deleting the last row of a table, the redraw/validate causes the entire table to be redrawn, not just the visible part. For tables with many rows, read from a DB or other persistent storage, this results in long UI delays (e.g. 15 secs for a 3'000 row table).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the code. It will print "getValueAt(n,0)" for the first twenty rows or so. Scroll to the end of table. This will print "getValueAt(n,0)" for the remaining ~980 rows.
Now press the delete button.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After deleting the last row, getValueAt() should only be called for one or two rows, or maybe twenty if there is no backing image store to scroll.
ACTUAL -
After deleting the last row, getValueAt() is called for all 1000 rows.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class RowDeleteBug extends JFrame {
private RowDeleteTableModel tableModel;
public RowDeleteBug() {
super("RowDeleteBug");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
JTable table = new JTable(tableModel = new RowDeleteTableModel(1000));
getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
JButton button = new JButton("Delete");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tableModel.deleteRow();
}
});
getContentPane().add(button, BorderLayout.SOUTH);
setSize(400, 400);
}
public static void main(String[] args) {
new RowDeleteBug().setVisible(true);
}
}
class RowDeleteTableModel extends AbstractTableModel {
private int rowCount;
RowDeleteTableModel(int initialRowCount) { rowCount = initialRowCount; }
public int getRowCount() { return rowCount; }
public int getColumnCount() { return 1; }
public Object getValueAt(int row, int col) {
System.out.println("getValueAt(" + row + "," + col + ")");
return "Item #" + row;
}
void deleteRow() {
rowCount--; fireTableRowsDeleted(rowCount, rowCount);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Overriding the table's getRowAtPoint() method to not return -1, but getRowCount() - 1 if the y coordinate exceeds the real table height, causes the bug to disappear.