-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
1.3.1_06, 1.4.1
-
x86
-
windows_98
Name: jk109818 Date: 04/14/2003
FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
FULL OS VERSION :
Windows 98 [Version 4.10.2222]
A DESCRIPTION OF THE PROBLEM :
When a JButton is used with a custom CellEditor and is mouse-clicked, then its row is not selected under these conditions:
- The row of the clicked button is the same as that of the previously clicked button.
- The table content was refreshed between the 2 button clicks.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use the provided testcase.
1) Click on button in row 3 (index 2)
2) Click on button "Refresh"
3) Go to 1)
EXPECTED VERSUS ACTUAL BEHAVIOR :
The value selectedRow in the dialog should always be 2.
The value selectedRow in the dialog is -1 and the table row is not selected.
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 SelectionLost extends javax.swing.JFrame{
private boolean workaround = false;
private int previousSelectedRow;
final int columnCount = 2;
String[] dataArray1 = new String[]{"0", "1", "2"};
String[] dataArray2 = new String[]{"0", "1", "2", "3", "4"};
String[] dataArray = dataArray1;
// Provide a single button instance to be re-used for rendering all rows
private final JButton renderButton = new JButton("...");
// Provide a single button instance to be re-used for editing in all rows
private final JButton clickButton = new JButton("...");
public SelectionLost() {
initComponents();
TableCellRenderer buttonRenderer = new TableCellRenderer(){
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column){
return renderButton;
}// method
};// anon class
jTable1.setDefaultRenderer(JButton.class, buttonRenderer);
ButtonCellEditor buttonEditor = new ButtonCellEditor(clickButton);
jTable1.setDefaultEditor(JButton.class, buttonEditor);
clickButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
int selectedRow = jTable1.getSelectedRow();
// The workaround exploits the fact that the bug only occurs
// when the selection is not changed: It uses the previous
// selection.
if(workaround){
if(selectedRow == -1){
selectedRow = previousSelectedRow;
}// if
else{
previousSelectedRow = selectedRow;
}// else
}// if
JOptionPane.showMessageDialog(null, "selectedRow = " + selectedRow);
}//method
});
}// constr
public static void main(String args[]) {
new SelectionLost().show();
}
private void initComponents() {
jPanelTop = new javax.swing.JPanel();
jButtonRefresh = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);
}
});
jButtonRefresh.setText("Refresh");
jButtonRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonRefreshActionPerformed(evt);
}
});
jPanelTop.add(jButtonRefresh);
getContentPane().add(jPanelTop, java.awt.BorderLayout.NORTH);
jTable1.setModel(getTableModel());
jScrollPane1.setViewportView(jTable1);
getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
pack();
}
private void jButtonRefreshActionPerformed(java.awt.event.ActionEvent evt) {
refresh();
}
private void exitForm(java.awt.event.WindowEvent evt) {
System.exit(0);
}
private TableModel getTableModel(){
// Create a model of the data.
TableModel dataModel = new AbstractTableModel() {
// These methods always need to be implemented.
public int getColumnCount() { return columnCount; }
public final int getRowCount() { return dataArray.length;}
public Object getValueAt(int row, int col) {
switch(col){
case 0:{
return dataArray[row];
}
case 1:{
return renderButton;
}
}// switch
return null;
}// method
public Class getColumnClass(int col) {return getValueAt(0,col).getClass();}
// The row containing the buttons must be editable
public boolean isCellEditable(int row, int col) {return (col==1);}
};
return dataModel;
}// method
private void refresh(){
// Toggle between 2 sets of data
if(dataArray == dataArray1){
dataArray = dataArray2;
}// if
else{
dataArray = dataArray1;
}// else
((AbstractTableModel)this.jTable1.getModel()).fireTableDataChanged();
// Clear any previous selection that would be meaningless with new data.
this.jTable1.clearSelection();
}// method
private javax.swing.JButton jButtonRefresh;
private javax.swing.JPanel jPanelTop;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
}// class
public class ButtonCellEditor extends AbstractCellEditor implements TableCellEditor{
private JButton sharedButton;
public ButtonCellEditor(JButton sharedButton){
this.sharedButton=sharedButton;
}// constr
// implementing TableCellEditor
public Component getTableCellEditorComponent(
JTable table,
Object value,
boolean isSelected,
int row,
int column){
return sharedButton;
}// method
// implementing CellEditor
public Object getCellEditorValue(){
return sharedButton;
}// method
}// class
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Please refer to the source code. It contains a flag "workaround"
(Review ID: 183298)
======================================================================
FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
FULL OS VERSION :
Windows 98 [Version 4.10.2222]
A DESCRIPTION OF THE PROBLEM :
When a JButton is used with a custom CellEditor and is mouse-clicked, then its row is not selected under these conditions:
- The row of the clicked button is the same as that of the previously clicked button.
- The table content was refreshed between the 2 button clicks.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use the provided testcase.
1) Click on button in row 3 (index 2)
2) Click on button "Refresh"
3) Go to 1)
EXPECTED VERSUS ACTUAL BEHAVIOR :
The value selectedRow in the dialog should always be 2.
The value selectedRow in the dialog is -1 and the table row is not selected.
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 SelectionLost extends javax.swing.JFrame{
private boolean workaround = false;
private int previousSelectedRow;
final int columnCount = 2;
String[] dataArray1 = new String[]{"0", "1", "2"};
String[] dataArray2 = new String[]{"0", "1", "2", "3", "4"};
String[] dataArray = dataArray1;
// Provide a single button instance to be re-used for rendering all rows
private final JButton renderButton = new JButton("...");
// Provide a single button instance to be re-used for editing in all rows
private final JButton clickButton = new JButton("...");
public SelectionLost() {
initComponents();
TableCellRenderer buttonRenderer = new TableCellRenderer(){
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column){
return renderButton;
}// method
};// anon class
jTable1.setDefaultRenderer(JButton.class, buttonRenderer);
ButtonCellEditor buttonEditor = new ButtonCellEditor(clickButton);
jTable1.setDefaultEditor(JButton.class, buttonEditor);
clickButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
int selectedRow = jTable1.getSelectedRow();
// The workaround exploits the fact that the bug only occurs
// when the selection is not changed: It uses the previous
// selection.
if(workaround){
if(selectedRow == -1){
selectedRow = previousSelectedRow;
}// if
else{
previousSelectedRow = selectedRow;
}// else
}// if
JOptionPane.showMessageDialog(null, "selectedRow = " + selectedRow);
}//method
});
}// constr
public static void main(String args[]) {
new SelectionLost().show();
}
private void initComponents() {
jPanelTop = new javax.swing.JPanel();
jButtonRefresh = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);
}
});
jButtonRefresh.setText("Refresh");
jButtonRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonRefreshActionPerformed(evt);
}
});
jPanelTop.add(jButtonRefresh);
getContentPane().add(jPanelTop, java.awt.BorderLayout.NORTH);
jTable1.setModel(getTableModel());
jScrollPane1.setViewportView(jTable1);
getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
pack();
}
private void jButtonRefreshActionPerformed(java.awt.event.ActionEvent evt) {
refresh();
}
private void exitForm(java.awt.event.WindowEvent evt) {
System.exit(0);
}
private TableModel getTableModel(){
// Create a model of the data.
TableModel dataModel = new AbstractTableModel() {
// These methods always need to be implemented.
public int getColumnCount() { return columnCount; }
public final int getRowCount() { return dataArray.length;}
public Object getValueAt(int row, int col) {
switch(col){
case 0:{
return dataArray[row];
}
case 1:{
return renderButton;
}
}// switch
return null;
}// method
public Class getColumnClass(int col) {return getValueAt(0,col).getClass();}
// The row containing the buttons must be editable
public boolean isCellEditable(int row, int col) {return (col==1);}
};
return dataModel;
}// method
private void refresh(){
// Toggle between 2 sets of data
if(dataArray == dataArray1){
dataArray = dataArray2;
}// if
else{
dataArray = dataArray1;
}// else
((AbstractTableModel)this.jTable1.getModel()).fireTableDataChanged();
// Clear any previous selection that would be meaningless with new data.
this.jTable1.clearSelection();
}// method
private javax.swing.JButton jButtonRefresh;
private javax.swing.JPanel jPanelTop;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
}// class
public class ButtonCellEditor extends AbstractCellEditor implements TableCellEditor{
private JButton sharedButton;
public ButtonCellEditor(JButton sharedButton){
this.sharedButton=sharedButton;
}// constr
// implementing TableCellEditor
public Component getTableCellEditorComponent(
JTable table,
Object value,
boolean isSelected,
int row,
int column){
return sharedButton;
}// method
// implementing CellEditor
public Object getCellEditorValue(){
return sharedButton;
}// method
}// class
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Please refer to the source code. It contains a flag "workaround"
(Review ID: 183298)
======================================================================
- duplicates
-
JDK-4777756 JTable doesn't remove active CellEditor when TableModel changes
-
- Open
-