TableView - 编辑聚焦单元格

时间:2015-02-11 13:58:42

标签: java javafx focus tableviewcell

我有一个侦听键盘事件的事件监听器。当我尝试使用键事件进入编辑模式时,由于某些奇怪的原因,不正确的单元格进入编辑模式。

例如,我想编辑一个单元格。我使用键盘箭头转到我想要编辑的单元格,即聚焦的单元格。通过单击键盘上的字母,焦点单元格应进入编辑模式。当我尝试编辑聚焦单元格时,错误的单元格进入编辑模式。

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与当前的单元格索引不同。我不确定为什么索引不同。

1 个答案:

答案 0 :(得分:6)

您的代码存在的问题是每个单元格在创建时都在调用table.setOnKeyPressed(...)。这与任何其他set方法一样,因此表上的keyPressed处理程序只设置为创建的最后一个EditCell。你无法控制细胞的实际创建,这不一定(并且不太可能)成为碰巧聚焦的细胞。

TableView有足够的API供您直接从表中管理。特别是

table.getFocusModel().getFocusedCell()

将为您提供代表当前焦点单元格的TablePosition。从那里你可以检索相应的行索引和TableColumn。然后你只需要调用table.edit(int row, TableColumn<...> column);来指示相应的单元格进入编辑模式。

这是一个完整的例子。我没有做太多努力来编辑&#34;漂亮&#34;在文本字段中选择文本等方面,您可能希望以某种方式实现编辑取消,但这应该让您开始。

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);
    }
}
相关问题