2010-12-20 5 views
7

Ich habe eine editierbare JTable und haben eine DefaultCellEditor wie so gesetzt:Warum wird cancelCellEditing() nicht aufgerufen, wenn während der Bearbeitung einer JTable-Zelle Escape gedrückt wird?

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

Wenn jedoch Flucht drücken, während eine Zelle in dieser Spalte bearbeiten, wenn der Bearbeitungsmodus beendet ist, wird diese Methode nicht aufgerufen. Irgendwelche Ideen warum? Mache ich etwas falsch? Gibt es eine Möglichkeit, dies zu handhaben (außer manuell das Hinzufügen eines KeyListener)?

Antwort

10

Der offizielle Weg: Sie können einen CellEditorListener registrieren: AbstractCellEditor.addCellEditorListener (...). Wenn die Bearbeitung abgebrochen wird, sollte die Bearbeitung von Canceled (ChangeEvent e) aufgerufen werden. Aufgrund eines SUN Bughttp://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6788481, editingCanceled nicht :(

Als Umgehung genannt Sie Ihre eigene Aktion für die Escape-Taste registrieren und verarbeiten es selbst. Aber es wird nicht für Resize-Events arbeiten.

Eine andere Lösung (schnell und schmutzig ;-)): Überschreibe die Methode JTable.removeEditor() und füge deinen Code nach dem Super-Aufruf ein.

+0

gut, das saugt. Vielen Dank. – Epaga

0

Ich hatte dieses Problem auch. Ich habe eine andere Problemumgehung geschrieben, die ActionListener und FocusListener beinhaltet. Das ist 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 Sie ein wenig komplettere Lösung finden können.

0

Ein anderer Weg fix diese Fehler:

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