2015-02-11 5 views
1

У меня есть прослушиватель событий, который прослушивает события клавиатуры. Когда я пытаюсь войти в режим редактирования, используя ключевое событие, по какой-то странной причине неправильная ячейка переходит в режим редактирования.TableView - редактирование сфокусированной ячейки

Например, я хочу отредактировать ячейку. Я использую стрелки клавиатуры, чтобы перейти к ячейке, которую я хочу редактировать, т. Е. Ячейке, которая сфокусирована. Нажимая букву на клавиатуре, сфокусированная ячейка должна перейти в режим редактирования. Когда я пытаюсь отредактировать сфокусированную ячейку, неправильная ячейка переходит в режим редактирования.

private final class EditCell extends TableCell<SimpleStringProperty, String> implements GenericTable 
{ 

    public EditCell() 
    { 
     // Add event listsner. table is a TableView 
     table.setOnKeyPressed(keyEvent -> this.handleKeyPressed(keyEvent)); 
    } 

    public void handleKeyPressed(KeyEvent key) 
    { 
     // Keyboard events 
     if (key.getCode().isLetterKey()) 
     { 
      if (!this.isEditing()) 
      { 

       this.edit = true; 

       // focus index 
       int focusIndex = this.table.getSelectionModel().getFocusedIndex(); 

       this.changeTableCellFocus(this.table, focusIndex); 

       this.startEdit(); 
      } 
     } 
    } 


    // startEdit() function 
    @Override 
    public void startEdit() 
    { 
     if (this.edit) 
     { 
      LOGGER.info("Start editing on cell index: " + this.getIndex()); 
      super.startEdit(); 
      this.createTextField(); 
      this.setText(null); 
      this.setGraphic(this.textField); 
      this.textField.selectAll(); 
      this.textField.requestFocus(); 

      this.textField.setOnKeyPressed(keyEvent -> this.handleKeyPressed(keyEvent)); 

      this.textField.focusedProperty() 
        .addListener((observable, oldValue, newValue) -> this.onTextFieldFocusChange(observable, 
          oldValue, 
          newValue)); 
     } 
    } 

    // Change focus 
    public void changeTableCellFocus(final TableView<?> table, final int focusIndex) 
    { 
     table.requestFocus(); 
     table.getSelectionModel().clearAndSelect(focusIndex); 
     table.getFocusModel().focus(focusIndex); 
    } 
} 

Перед тем, как войти в режим редактирования, я сменю фокус на щелканную ячейку и вызову метод startEdit(). Я попытался отладить проблему, но не повезло. Я заметил, что focusIndex отличается от текущего индекса ячейки. Я не уверен, почему индекс отличается.

+0

Можете ли вы привести этот код в какой-то контекст? Это в подклассе 'TableCell'? –

+0

Вы пытались использовать выбор вместо фокуса? Я думаю, что редактирование таблицы основано на выборе не на фокусе. – eckig

+0

Функция changeTableCellFocus (...) выбирает ячейку + помещает фокус на ячейку. Вы имеете в виду, просто выберите ячейку, а затем вызовите startEdit(). Я думаю, проблема заключается в том, что текущий индекс ячейки отличается от индекса ячейки фокуса, а это означает, что даже если вы измените выбранную ячейку на сфокусированную ячейку индекса, у вас все еще будет проблема, так как в текущей ячейке вызывается функция startEdit(). – breaktop

ответ

5

Проблема с вашим кодом заключается в том, что каждая ячейка вызывает table.setOnKeyPressed(...) по мере ее создания. Это работает, как и любой другой метод set, поэтому обработчик keyPressed на столе только что установлен на один из последних EditCell, который был создан. У вас нет контроля над фактическим созданием ячеек, и это не обязательно (и маловероятно) быть ячейкой, которая, по-видимому, фокусируется.

TableView имеет достаточно API, чтобы вы могли управлять этим непосредственно из таблицы. В частности

table.getFocusModel().getFocusedCell() 

предоставит вам TablePosition, представляющий ячейку, сфокусированную в настоящее время. Из этого вы можете получить соответствующий индекс строки и TableColumn. Тогда вам просто нужно позвонить table.edit(int row, TableColumn<...> column);, чтобы дать указание соответствующей ячейке перейти в режим редактирования.

Вот полный пример. Я не прилагал особых усилий, чтобы сделать редактирование «красивым» с точки зрения выбора текста и т. Д. В текстовом поле, и вы можете каким-то образом реализовать редактирование, но это должно вас начать.

import java.util.ArrayList; 
import java.util.List; 

import javafx.application.Application; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.scene.Scene; 
import javafx.scene.control.ContentDisplay; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TablePosition; 
import javafx.scene.control.TableView; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class TableViewEditOnType extends Application { 


    @Override 
    public void start(Stage primaryStage) { 
     TableView<List<StringProperty>> table = new TableView<>(); 
     table.getSelectionModel().setCellSelectionEnabled(true); 
     table.setEditable(true); 

     for (int i = 0; i < 10; i++) { 
      table.getColumns().add(createColumn(i)); 

      List<StringProperty> rowData = new ArrayList<>(); 
      table.getItems().add(rowData); 
      for (int j = 0; j < 10 ; j++) { 
       rowData.add(new SimpleStringProperty(String.format("Cell [%d, %d]", i, j))); 
      } 
     } 

     table.setOnKeyTyped(event -> { 
      TablePosition<List<StringProperty>, String> focusedCell = table.getFocusModel().getFocusedCell(); 
      if (focusedCell != null) { 
       table.getItems().get(focusedCell.getRow()).get(focusedCell.getColumn()).set(event.getCharacter()); 
       table.edit(focusedCell.getRow(), focusedCell.getTableColumn()); 
      } 
     }); 

     Scene scene = new Scene(new BorderPane(table), 880, 600); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private TableColumn<List<StringProperty>, String> createColumn(int colIndex) { 
     TableColumn<List<StringProperty>, String> col = new TableColumn<>("Column "+colIndex); 
     col.setCellValueFactory(cellData -> cellData.getValue().get(colIndex)); 
     col.setCellFactory(column -> new EditCell()); 
     return col ; 
    } 

    private static class EditCell extends TableCell<List<StringProperty>, String> { 

     private final TextField textField = new TextField(); 

     EditCell() { 
      textProperty().bind(itemProperty()); 
      setGraphic(textField); 
      setContentDisplay(ContentDisplay.TEXT_ONLY); 

      textField.setOnAction(evt -> commitEdit(textField.getText())); 
      textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { 
       if (! isNowFocused) { 
        commitEdit(textField.getText()); 
       } 
      }); 
     } 

     @Override 
     public void startEdit() { 
      super.startEdit(); 
      textField.setText(getItem()); 
      setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
      textField.requestFocus();   
     } 

     @Override 
     public void cancelEdit() { 
      super.cancelEdit(); 
      setContentDisplay(ContentDisplay.TEXT_ONLY); 
     } 

     @Override 
     public void commitEdit(String text) { 
      super.commitEdit(text); 
      setContentDisplay(ContentDisplay.TEXT_ONLY); 
     } 

    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

Именно то, что я искал. Спасибо @James_D – breaktop

+0

Спасибо, отличный образец. – chris

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

  • Нет связанных вопросов^_^