2015-02-11 107 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'子类中? – 2015-02-11 14:08:15

+0

你是否尝试使用选择而不是焦点?我猜表格编辑是基于选择而不是焦点。 – eckig 2015-02-11 14:17:06

+0

changeTableCellFocus(...)函数选择单元格+将焦点放在单元格上。你的意思是,只要选择单元格,然后调用startEdit()。我认为问题在于当前单元格索引与焦点单元格索引不同,这意味着即使将所选单元格更改为焦点索引单元格,仍然会遇到问题,因为在当前单元格中调用了startEdit()。 – breaktop 2015-02-11 14:26:45

回答

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 2015-02-13 14:54:08

+0

谢谢你,很棒的示例。 – chris 2015-04-07 21:07:23