2010-12-20 20 views
7

Tengo una JTable editable y he puesto un DefaultCellEditor así:¿Por qué no se llama a cancelCellEditing() al presionar escape mientras se edita una celda JTable?

colModel.getColumn(1).setCellEditor(new DefaultCellEditor(txtEditBox) { 
     // ... 
     @Override 
     public void cancelCellEditing() { 
      super.cancelCellEditing(); 
      // handling the event 
     } 
     // ... 
    } 

Sin embargo, cuando presionando escape durante la edición de una célula en esta columna, aunque el modo de edición está terminada, este método no se llama. ¿Alguna idea de por qué? ¿Estoy haciendo algo mal? ¿Hay alguna forma de manejar esto (aparte de agregar manualmente un KeyListener)?

Respuesta

10

La manera oficial: Puede registrar un CellEditorListener: AbstractCellEditor.addCellEditorListener (...). Si se cancela la edición, se debe invocar a editingCanceled (ChangeEvent e). Debido a un error SUNhttp://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6788481, editingCanceled no se llama :(

Como solución alternativa puede registrar su propia acción de la tecla Escape y manejar por sí mismo. Pero no va a trabajar para los eventos de cambio de tamaño.

Otra solución (rápida y sucia ;-)): sobrescribe el método JTable.removeEditor() e inserte su código después de la súper llamada.

+0

bien que chupa. Gracias. – Epaga

0

Tuve este problema también. Escribí otra solución que implica ActionListener y FocusListener. Esto es:

public class TableEditorListenerHelper { 

// dealing with events 
private final EventListenerList listeners = new EventListenerList(); 
private ChangeEvent changeEvent; 

// cell editor that we're helping 
private CellEditor editor; 

// transient state 
private boolean editing = false; 
private JTable table; 

public TableEditorListenerHelper(CellEditor editor, JTextField field) { 
    this.editor = editor; 
    field.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent e) { 
      fireEditingStopped(); 
     } 
    }); 
    field.addFocusListener(new FocusListener() { 

     @Override public void focusGained(FocusEvent e) { 
      editing = true; 
     } 

     @Override public void focusLost(FocusEvent e) { 
      JTable table = TableEditorListenerHelper.this.table; 
      if (editing && isEditing(table)) { 
       fireEditingCanceled(); 
      } 
     } 

     private boolean isEditing(JTable table) { // a hack necessary to deal with focuslist vs table repaint 
      return table != null && table.isEditing(); 
     } 

    }); 
} 

public void setTable(JTable table) { 
    this.table = table; 
} 

public void addCellEditorListener(CellEditorListener l) { 
    listeners.add(CellEditorListener.class, l); 
} 

public void removeCellEditorListener(CellEditorListener l) { 
    listeners.remove(CellEditorListener.class, l); 
} 

public CellEditorListener[] getCellEditorListeners() { 
    return listeners.getListeners(CellEditorListener.class); 
} 

protected void fireEditingCanceled() { 
    for (CellEditorListener l : getCellEditorListeners()) { 
     l.editingCanceled(getOrCreateEvent()); 
    } 
    resetEditingState(); 
} 

protected void fireEditingStopped() { 
    for (CellEditorListener l : getCellEditorListeners()) { 
     l.editingStopped(getOrCreateEvent()); 
    } 
    resetEditingState(); 
} 

private void resetEditingState() { 
    table = null; 
    editing = false; 
} 

private ChangeEvent getOrCreateEvent() { 
    return changeEvent = changeEvent == null ? new ChangeEvent(editor) : changeEvent; 
} 

Here se puede encontrar una pequeña solución más completa.

0

Otra forma solución este fallo:

jTable.addPropertyChangeListener("tableCellEditor", e -> { 
    Object o = e.getOldValue(); 
    if (o instanceof DefaultCellEditor) { 
     ((DefaultCellEditor) o).cancelCellEditing(); 
    } 
}); 
Cuestiones relacionadas