2015-02-11 82 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

相關問題