有没有人想出如何让javafx tableview像jtable一样?

时间:2013-04-09 03:10:34

标签: java swing jtable javafx tableview

我从offical tableview tutorial跟踪了示例13-11单元格编辑的替代解决方案,但我希望我的tableview充当jtable。这意味着当一个单元格获得焦点时,它就可以进行编辑了,使用箭头键或Enter键可以立即提交编辑并移动到下一个单元格。

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

首先,我添加了

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键两次才能结束编辑,它不会提交编辑,而是取消编辑。

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:1)

遗憾的是,该教程缺少一些代码修补程序,这些修补程序稍后在TextFieldTableCell类中引入,以使ENTER正常工作(RT-34685 - Use onAction instead of onKeyPressedRT-28132 - Call 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();
    }
}

希望这有帮助!