如何通知TableCellEditor删除表行?

时间:2012-01-10 09:46:04

标签: java swing jtable tablecelleditor abstracttablemodel

我尝试实现一个具有某些字段和删除按钮的TableCellEditor。它运行良好,但删除行时,已删除单元格中的内容(使用TableCellEditor呈现)更新。

当删除行时,我试图在模型中同时调用fireTableRowsDeleted(row, row)fireTableDataChanged(),但它似乎没有通知TableCellEditor。它在我选择另一行时有效,并且再次使用TableCellRenderer呈现行索引。

有关如何在删除时通知TableCellEditor的任何建议?

  1. 按下删除按钮

    enter image description here

  2. 已删除行,但未更新CellEditor内容

    enter image description here

  3. 当再次使用CellRenderer时,行内容已更新。

    enter image description here

  4. 以下是代码:

    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();
                }
    
            });
        }
    }
    

1 个答案:

答案 0 :(得分:4)

这是因为当您点击删除按钮时,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();
    }
  });
}