6

我遵循了官方 tableview 教程中的示例 13-11 单元格编辑的替代解决方案,但我希望我的行为像. 这意味着当一个单元格获得焦点时,就可以对其进行编辑了,使用箭头键或 Enter 键应该会立即提交编辑并移至下一个单元格。tableviewjtable

这是我到目前为止所做的:

首先,我添加了

table.getSelectionModel().setCellSelectionEnabled(true);

然后我尝试修改类EditingCell

class EditingCell extends TableCell<Person, String> {

    private TextField textField;

    public EditingCell() {
    }

    @Override
    public void updateSelected(boolean selected) {
        super.updateSelected(selected);
        if (selected) {
            createTextField();
            setText(null);
            setGraphic(textField);
            textField.requestFocus();
            textField.selectAll();
        } else {
            String value = textField.getText();
            if (value != null) {
                commitEdit(value);
            } else {
                commitEdit(null);
            }
        }
    }


    @Override
    public void cancelEdit() {
        super.cancelEdit();

        setText((String) getItem());
        setGraphic(null);
    }

    @Override
    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            if (isEditing()) {
                if (textField != null) {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else {
                setText(getString());
                setGraphic(null);
            }
        }
    }

    private void createTextField() {
        textField = new TextField(getString());
        textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
        textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> arg0,
                    Boolean arg1, Boolean arg2) {
                if (!arg2) {
                    commitEdit(textField.getText());
                }
            }
        });
        textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if ((t.getCode() == KeyCode.ENTER) || (t.getCode() == KeyCode.UP) || (t.getCode() == KeyCode.DOWN) || (t.getCode() == KeyCode.LEFT) || (t.getCode() == KeyCode.RIGHT)) {
                    t.consume();
                    String value = textField.getText();
                    if (value != null) {
                        commitEdit(value);
                    } else {
                        commitEdit(null);
                    }
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });
    }

    private String getString() {
        return getItem() == null ? "" : getItem().toString();
    }
}

我得到的tableview是一团糟 - 我必须单击两次 Enter 键才能结束编辑,它不会提交编辑而是取消它。

谁能指出我正确的方向?

4

1 回答 1

1

遗憾的是,该教程缺少一些稍后在 TextFieldTableCell 类中引入的代码修复,以便 ENTER 正常工作(RT-34685 - 使用 onAction 而不是 onKeyPressedRT-28132 - 调用 requestFocus())。

这是一个工作示例,它是TextFieldTableCell代码的简化版本,它还使用Node.fireEvent()在提交后移动到下一个单元格(模仿 KeyPressed 事件):

class EditingCell extends TableCell<Person, String>
{
    private TextField   textField;

    public EditingCell()
    {
    }

    @Override
    public void startEdit()
    {
        if (!isEditable() || !getTableView().isEditable()
                || !getTableColumn().isEditable())
        {
            return;
        }
        super.startEdit();

        if (isEditing())
        {
            if (textField == null)
            {
                createTextField();
            }
            setText(null);
            setGraphic(textField);
            textField.selectAll();
            // requesting focus so that key input can immediately go into
            // the TextField (see RT-28132)
            textField.requestFocus();
        }
    }

    @Override
    public void cancelEdit()
    {
        super.cancelEdit();

        setText((String) getItem());
        setGraphic(null);
    }

    @Override
    public void updateItem(String item, boolean empty)
    {
        super.updateItem(item, empty);

        if (empty)
        {
            setText(null);
            setGraphic(null);
        } else
        {
            if (isEditing())
            {
                if (textField != null)
                {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else
            {
                setText(getString());
                setGraphic(null);
            }
        }
    }

    private void createTextField()
    {
        textField = new TextField(getString());
        textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
        textField.focusedProperty().addListener(new ChangeListener<Boolean>()
        {
            @Override
            public void changed(ObservableValue<? extends Boolean> arg0,
                    Boolean arg1, Boolean arg2)
            {
                if (!arg2)
                {
                    commitEdit(textField.getText());
                }
            }
        });

        // Use onAction here rather than onKeyReleased (with check for
        // Enter), as otherwise we encounter RT-34685
        textField.setOnAction(t -> {
            commitEdit(textField.getText());
            t.consume();
        });
        textField.setOnKeyReleased(t -> {
            if (t.getCode() == KeyCode.ESCAPE)
            {
                cancelEdit();
                t.consume();
            }
        });

        textField.setOnKeyPressed(new EventHandler<KeyEvent>()
        {
            @Override
            public void handle(KeyEvent t)
            {
                if ((t.getCode() == KeyCode.UP) || (t.getCode() == KeyCode.DOWN)
                        || (t.getCode() == KeyCode.LEFT)
                        || (t.getCode() == KeyCode.RIGHT))
                {
                    // Commit the current text
                    commitEdit(textField.getText());

                    // Let's move out simulating a key press in this Cell
                    KeyEvent event = new KeyEvent(t.getSource(), t.getTarget(),
                            KeyEvent.KEY_PRESSED, "", "", t.getCode(), false, false,
                            false, false);
                    EditingCell.this.fireEvent(event);
                }
            }
        });
    }

    private String getString()
    {
        return getItem() == null ? "" : getItem().toString();
    }
}

希望这可以帮助!

于 2016-09-12T21:09:33.007 回答