我尝试实现一个包含一些字段的TableCellEditor和一个删除按钮。它运行良好,但是当删除行时,删除单元格(用TableCellEditor呈现)中的内容是而不是更新的。
当删除行时,我尝试同时调用模型中的fireTableRowsDeleted(row, row)和fireTableDataChanged(),但它似乎没有通知TableCellEditor。当我选择另一行时,它可以工作,并且行索引再次用TableCellRenderer呈现。
对删除时如何通知TableCellEditor有任何建议吗?



以下是代码:
public class StringTableDemo extends JFrame {
public StringTableDemo() {
final StringTableModel model = new StringTableModel();
model.addRow("Jonas");
model.addRow("Hello");
model.addRow("World");
RendererAndEditor rendererAndEditor = new RendererAndEditor(model);
JTable table = new JTable(model);
table.setDefaultRenderer(Record.class, rendererAndEditor);
table.setDefaultEditor(Record.class, rendererAndEditor);
add(new JScrollPane(table), BorderLayout.CENTER);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
class Record {
String string;
boolean isDeleted;
}
class StringTableModel extends AbstractTableModel {
private final List<Record> data = new ArrayList<Record>();
@Override
public int getColumnCount() {
return 1;
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public Object getValueAt(int row, int column) {
return data.get(row);
}
@Override
public Class<?> getColumnClass(int column) {
return Record.class;
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if(aValue instanceof Record) {
Record r = (Record)aValue;
if(!r.isDeleted) {
data.set(row, r);
fireTableRowsUpdated(row, column);
}
} else throw new IllegalStateException("aValue is not a Record");
}
public void addRow(String s) {
Record r = new Record();
r.string = s;
r.isDeleted = false;
data.add(r);
fireTableRowsInserted(data.size()-1, data.size()-1);
}
public void removeRow(int row) {
data.remove(row);
//fireTableRowsDeleted(row, row);
fireTableDataChanged();
System.out.println("row " + row + " deleted");
}
}
class CellPanel extends JPanel {
private final Action removeAction = new AbstractAction("x") {
@Override
public void actionPerformed(ActionEvent arg0) {
model.removeRow(index);
isDeleted = true;
}
};
private final JButton removeBtn = new JButton(removeAction);
private final JTextField field = new JTextField();
private final StringTableModel model;
private int index;
private boolean isDeleted = false;
public CellPanel(StringTableModel model) {
super(new BorderLayout());
this.model = model;
add(field, BorderLayout.CENTER);
add(removeBtn, BorderLayout.EAST);
}
public Record getRecord() {
Record r = new Record();
r.string = field.getText();
r.isDeleted = isDeleted;
return r;
}
public void setRecord(Record r, int index) {
field.setText(r.string);
this.index = index;
}
}
class RendererAndEditor extends AbstractCellEditor implements
TableCellEditor, TableCellRenderer {
private final CellPanel renderer;
private final CellPanel editor;
public RendererAndEditor(StringTableModel model) {
renderer = new CellPanel(model);
editor = new CellPanel(model);
}
@Override
public Object getCellEditorValue() {
return editor.getRecord();
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
renderer.setRecord((Record)value, row);
return renderer;
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
editor.setRecord((Record)value, row);
return editor;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new StringTableDemo();
}
});
}
}发布于 2012-01-10 09:58:26
这是因为当您单击“删除”按钮时,您的CellEditor没有注意到它必须停止编辑单元格。
一个简单的解决方案是将另一个ActionListener添加到您的CellEditor中,每次单击它时都调用stopCellEditing()。这应该是可行的:
public RendererAndEditor( StringTableModel model )
{
renderer = new CellPanel( model );
editor = new CellPanel( model );
editor.getRemoveBtn().addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
stopCellEditing();
}
});
}https://stackoverflow.com/questions/8801210
复制相似问题