对TableView JavaFx中的所有单元格调用cancelEdit



我正在使用一个自定义的可编辑表单元格工厂,我已经工作了一段时间。我目前正在实现一个功能,允许单击开始编辑。

我有一个点击开始单元格编辑,但是如果你点击另一个单元格一次,以前的不关闭。我的想法是在打开点击单元格进行编辑之前,循环遍历调用cancelEdit()的所有单元格。

下面是我正在使用的整个单元格类(双击编辑即可)。我正在处理的部分在构造函数中。

public class EditingCell<S, T> extends TableCell<S, T> {
    private TextField textField;
    public EditingCell() {
        TableView<S> table = this.getTableView();
        addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                for(TableColumn<S, ?> col : table.getColumns()) {
                    // cancelEdit() on all cells here
                }
                startEdit();
            }
        });
    }
    public void commit(Object val) {
        commit(val, this.getTableRow().getIndex(), getTableView().getColumns().indexOf(this.getTableColumn()));
    }
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void commit(Object val, int row, int col) {
        // Get the table
        TableView<S> t = this.getTableView();
        // Get the selected row/column
        S selectedRow = t.getItems().get(row);
        if (selectedRow == null)
            return;
        TableColumn<S, ?> selectedColumn = t.getColumns().get(col);
        // Get current property name
        String propertyName = ((PropertyValueFactory) selectedColumn.getCellValueFactory()).getProperty();
        // Create a method name conforming to java standards ( setProperty )
        propertyName = ("" + propertyName.charAt(0)).toUpperCase() + propertyName.substring(1);
        // Try to run the update
        try {
            // Type specific checks - could be done inside each
            // setProperty() method
            if (val instanceof Double) {
                Method method = selectedRow.getClass().getMethod("set" + propertyName, double.class);
                method.invoke(selectedRow, (double) val);
            }
            if (val instanceof String) {
                Method method = selectedRow.getClass().getMethod("set" + propertyName, String.class);
                method.invoke(selectedRow, (String) val);
            }
            if (val instanceof Integer) {
                Method method = selectedRow.getClass().getMethod("set" + propertyName, int.class);
                method.invoke(selectedRow, (int) val);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // CommitEdit for good luck
        commitEdit((T) val);
        TableUtils.Refresh(t, t.getItems());
    }
    @Override
    public void startEdit() {
        if (!isEmpty()) {
            super.startEdit();
            createTextField();
            setText(null);
            setGraphic(textField);
            textField.selectAll();
        }
    }
    @Override
    public void cancelEdit() {
        super.cancelEdit();
        String val = "0.0";
        if (!textField.getText().equals(""))
            val = "" + Double.parseDouble(textField.getText());
        setText(NumberUtils.roundTo2(NumberUtils.parseDouble(val)) + "");
        setGraphic(null);
    }
    @Override
    public void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setText("");
            setGraphic(null);
        } else {
            if (isEditing()) {
                if (textField != null) {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else {
                setText(NumberUtils.roundTo3(NumberUtils.parseDouble(getString())) + "");
                setGraphic(null);
            }
        }
    }
    @SuppressWarnings({ "rawtypes" })
    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) {
                    if (textField.getText().equals(""))
                        commit(0.0);
                    else {
                        double val = Double.parseDouble(textField.getText());
                        commit(val);
                    }
                }
            }
        });
        textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
            if (event.getCode() == KeyCode.ESCAPE) {
                textField.setText("" + getItem());
                cancelEdit();
                event.consume();
            }
            // Navigate up and down in table
            else if (event.getCode() == KeyCode.ENTER) {
                TableView<S> table = getTableView();
                int row = table.getEditingCell().getRow();
                // Commit changes
                if (textField.getText().equals(""))
                    commit(0.0);
                else {
                    double val = Double.parseDouble(textField.getText());
                    commit(val);
                }
                // Do move
                if (event.isShiftDown())
                    table.edit(row - 1, getTableColumn());
                else {
                    table.edit(row + 1, getTableColumn());
                }
            }
            // Move left and right in table
            else if (event.getCode() == KeyCode.TAB) {
                TableView<S> table = getTableView();
                int row = table.getEditingCell().getRow();
                // Save changes
                if (textField.getText().equals(""))
                    commit(0.0);
                else {
                    double val = Double.parseDouble(textField.getText());
                    commit(val);
                }
                ArrayList<TableColumn<S, ?>> cols = new ArrayList<TableColumn<S, ?>>();
                int index = 0;
                for (TableColumn<S, ?> c : table.getColumns()) {
                    if (c.isVisible() && c.isEditable())
                        cols.add(c);
                    if (c == getTableColumn())
                        index = cols.size() - 1;
                }
                // Do move
                if (event.isShiftDown()) {
                    try {
                        TableColumn<S, ?> prevCol = cols.get(index - 1);
                        table.edit(row, prevCol);
                    } catch (Exception e) {
                    }
                } else {
                    try {
                        TableColumn<S, ?> nextCol = cols.get(index + 1);
                        table.edit(row, nextCol);
                    } catch (Exception e) {
                    }
                }
            }
        });
        textField.setTextFormatter(new TextFormatter<String>((Change c) -> {
            String text = c.getText();
            TableView<S> table = getTableView();
            if (table.getSelectionModel().getSelectedCells().size() == 0) {
                return c;
            }
            TablePosition pasteCellPosition = table.getSelectionModel().getSelectedCells().get(0);
            int clipRow = 0;
            int clipCol = 0;
            String curCellText = text;
            if (text.contains("t") || text.contains("n")) {
                StringTokenizer row = new StringTokenizer(text, "n");
                boolean hasRun = false;
                while (row.hasMoreTokens() || !hasRun) {
                    String r = row.nextToken();
                    StringTokenizer col;
                    if (r != null)
                        col = new StringTokenizer(r, "t");
                    else
                        col = new StringTokenizer(text, "t");
                    hasRun = true;
                    clipCol = 0;
                    while (col.hasMoreTokens()) {
                        String content = col.nextToken();
                        if (clipRow == 0 && clipCol == 0) {
                            curCellText = content;
                        }
                        // calculate the position in the table cell
                        int rowTable = pasteCellPosition.getRow() + clipRow;
                        int colTable = pasteCellPosition.getColumn() + clipCol;
                        // Skip hidden columns before current cell
                        for (int i = 0; i < colTable; i++)
                            if (!table.getColumns().get(i).isVisible())
                                colTable++;
                        // Skip hidden columns between current and goal
                        while (!table.getColumns().get(colTable).isVisible()) {
                            if (colTable >= table.getColumns().size())
                                break;
                            colTable++;
                        }
                        // Add row if we reach the end
                        if (rowTable >= table.getItems().size()) {
                            if (table.getItems().get(0) instanceof EditableTableRow)
                                ((EditableTableRow) table.getItems().get(0)).addRowToTable(table);
                            // continue;
                        }
                        if (colTable >= table.getColumns().size()) {
                            continue;
                        }
                        try {
                            double val = Double.parseDouble(content);
                            commit(val, rowTable, colTable);
                        } catch (Exception e) {
                            try {
                                int val = Integer.parseInt(content);
                                commit(val, rowTable, colTable);
                            } catch (Exception e2) {
                                commit(content, rowTable, colTable);
                            }
                        }
                        clipCol++;
                    }
                    clipRow++;
                }
            }
            c.setText(curCellText);
            return c;
        }));
        textField.requestFocus();
        textField.selectAll();
    }
    private String getString() {
        return getItem() == null ? "" : getItem().toString();
    }
}

你不能遍历所有单元格;您无法知道已经创建了哪些单元格,它们代表实际的项,等等。

你可以调用

getTableView().edit(-1, null);

将具有取消编辑的效果。(见Javadocs。)实际上,调用

可能更好
getTableView().edit(getIndex(), getTableColumn());

而不是调用startEdit()。这将(应该)?我还没有测试…)为你调用startEdit()。换句话说,

public EditingCell() {
    addEventFilter(MouseEvent.MOUSE_CLICKED, e -> 
        getTableView().edit(getIndex(), getTableColumn()));
}

作为一个题外话,为什么你去所有的麻烦使单元格实现非常一般,但然后假设单元格值工厂是PropertyValueFactory的一个实例?当然,你可以通过

获得单元格的可观察值
ObservableValue<T> obs = getTableColumn().getCellObservableValue(getTableView().getItems().get(getIndex()));

,然后按

if (obs instanceof WritableValue) {
    ((WritableValue<?>) obs).setValue(val);
}

最新更新