2012-01-10 4 views
3

Я пытаюсь реализовать TableCellEditor, который содержит некоторые поля и кнопку удаления. Он работает хорошо, но строка удаляется, содержимое в удаленной ячейке (отображается с помощью TableCellEditor) равно , а не.Как уведомить TableCellEditor о том, что строка таблицы удалена?

Я попытался позвонить как fireTableRowsDeleted(row, row), так и fireTableDataChanged() в модели, когда строка удалена, но она, похоже, не сообщает TableCellEditor. Он работает, когда я выбираю другую строку, а индекс строки снова отображается с помощью TableCellRenderer.

Любые предложения о том, как уведомить TableCellEditor об удалении?

  1. кнопка Delete нажата

    enter image description here

  2. Строка удалена, но содержание CellEditor не обновляется

    enter image description here

  3. Содержимое строки обновляется, когда CellRenderer используется снова.

    enter image description here

Вот код:

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

     }); 
    } 
} 
+0

Кстати, ваша реализация редактора (все еще нету, я видел это раньше ;-) недействителен – kleopatra

+1

вы уже приняли правильный ответ - это таким образом, ты понять мою мутную комментарий :-)? – kleopatra

ответ

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