2013-08-10 3 views
0

У меня есть JTable, который использует пользовательский TableModel. Я расширил класс AbstractCellEditor, и ячейка корректно отображает текст, введенный в текстовое поле, когда я дважды щелкаю текстовое поле. но когда я просто одним щелчком выбираю ячейку в таблице и начинаю вводить текст, текстовое поле получает текст, но когда я нажимаю клавишу ввода, он не обновляет текстовое поле. Я подключил прослушиватель фокуса к текстовому полю для устранения неполадок и обнаружил, что он только выигрывает и теряет фокус при двойном щелчке по полю. С одним щелчком он не получает фокус (хотя он позволяет мне редактировать его). Это ошеломило мой разум! Я пробовал textField.grabFocus(), textField.requestFocusInWindow() и всевозможные другие вещи. Какие-либо предложения? Благодаря!JTextField не обновляется при нажатии клавиши

public class IndexerCellEditor extends AbstractCellEditor implements 
    TableCellEditor { 
private JTextField textField; 
private RecordValue currentValue; 

public IndexerCellEditor(){ 
    textField = new JTextField(); 
} 

@Override 
public boolean isCellEditable(EventObject e){ 
    if(e instanceof MouseEvent){ 
     return ((MouseEvent)e).getClickCount() >= 2; 
    } 

    return true; 
} 


@Override 
public Object getCellEditorValue() { 
    return currentValue; 
} 


@Override 
public Component getTableCellEditorComponent(JTable table, Object value, 
     boolean isSelected, int row, int column) { 

    textField.setBorder(BorderFactory.createLineBorder(Color.black, 1)); 

    currentValue = (RecordValue) value; 

    textField.setText(currentValue.getValue()); 

    textField.addFocusListener(new FocusListener(){ 

     @Override 
     public void focusGained(FocusEvent e) { 
      System.out.println("focus gained"); 

     } 

     @Override 
     public void focusLost(FocusEvent e) { 
      System.out.println("focus lost"); 

     } 

    }); 

    textField.addActionListener(new ActionListener(){ 
     @Override 
     public void actionPerformed(ActionEvent e) { 

      currentValue.setValue(((JTextField)e.getSource()).getText()); 

      fireEditingStopped(); 
     } 
    }); 

    return textField; 
} 

} 
+0

Для сравнения см. Этот полный [пример] (http://stackoverflow.com/a/10067560/230513). – trashgod

+1

, потому что private RecordValue currentValue; имеет неправильный параметр (перегрузка), в строке 45. – mKorbel

+0

@mKorbel анонимные внутренние классы имеют доступ к закрытым переменным (currentValue) своего внешнего класса. Кроме того, приведенный выше код работает корректно, когда я DOUBLE CLICK на ячейке (см. Метод 'isCellEditable()'). Я просто не знаю, почему actionevent не запускается, когда я нажимаю кнопку и начинаю вводить текст, а затем нажмите 'enter'. – ejsuncy

ответ

-1

ИТАК примерно через 8 часов больше, ударив головой о стену, я обнаружил 2 вещи:

  1. мне не нужно слушатель действий на JTextField, потому что JTable принимает заботиться об этом для меня. Когда я ударил enter после двойного щелчка + типизации, или щелкните + типизации, JTable автоматически вызывает stopCellEditing(), что приводит меня к

  2. мне нужно переопределить stopCellEditing() в моем IndexerCellEditor классе, чтобы сохранить текст JTextField, прежде чем передать его на родитель. Код я пропускал:

    @Override 
    public boolean stopCellEditing(){ 
         currentValue = textField.getText(); 
         return super.stopCellEditing(); 
    } 
    

Надеется, что это помогает любому с той же проблемой.

EDIT Это работает в моем случае, потому что я также расширил DefaultTableModel, который берет на себя уведомления слушателей с помощью метода:

@Override 
public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
    cells[rowIndex][columnIndex] = (String) aValue; 
    fireTableCellUpdated(rowIndex, columnIndex); 
} 

Я проверил это несколько больше, создавая две различные таблицы с тем же расширенный DefaultTableModel. Размещая их бок о бок в JPanel, я мог бы редактировать одну ячейку в одной таблице, и после нажатия клавиши ввода она обновила и отредактированную ячейку, и ее соседнюю ячейку в другой таблице. Короче говоря, слушатели должны быть уведомлены с помощью метода вызова fire... где-то в проекте.

+1

Ваша пуля 1. _wrong_ - если вы не реализуете редактор, чтобы уведомить своих слушателей о завершении редактирования, реализация недействительна. Не добавляйте actionListener в getXX, вместо этого делайте это в contructor И будьте осторожны: фокус - это хрупкое свойство в редакторах (JTable имеет этот печально известный режим редактирования, где таблица сохраняет фокус и маршрутизирует keyEvents через processKeyBinding) – kleopatra

+0

, что последняя часть bullet 1 ('which bring me to) подразумевает, что 1 и 2 должны использоваться совместно. Я полностью удалил прослушиватель действий из своего текстового поля, но я переопределяю 'stopCellEditing()'. см. # 2 - я позволяю суперклассу заботиться об уведомлении с помощью 'super.stopCellEditing()'. Сейчас это прекрасно. – ejsuncy

+0

super только заботится о _mechanics_ уведомления - ответственность за конкретный подкласс лежит на самом деле _use_ the mechanics. Повторение: cellEditors (так же, как любая действительная реализация какого-либо api) _must соответствовать_ его контракту (vs.полагаясь на какой-то другой класс, случайно не снисходительный в определенных контекстах) – kleopatra

Смежные вопросы