JavaFx TableView - 如果将焦点放在同一列上,则保存对焦点丢失的编辑不起作用

时间:2016-06-06 15:05:14

标签: java javafx tableview

我一直在解决这个问题,似乎无法找到任何逻辑修复。

我试图在用户点击时保存表格单元格的内容。在关注this tutorial之后,当用户点击同一列时,我的表单元格会在焦点丢失时保存其编辑内容之外。

我知道问题发生的原因,如果commitEdit()为真,isEditing()方法会立即返回(当您点击同一列时就是这样。

 public void commitEdit(T newValue) {
        if (! isEditing()) return;
    ...

我尝试重写该方法无济于事。我可以强制更新单元格内容,但我不知道如何在不知道我所在的单元格的情况下强制编辑单元格值。

如果有办法让我获得我所在单元格的字段名称,我可以使用Reflection来强制更新,但我不知道如何获取字段名称或者是否知道该字段名称。甚至可能。

2 个答案:

答案 0 :(得分:1)

看起来你正在寻找的是一种让细胞处理新(或旧)值并将它们写回模型的方法。为什么不以BiConsumer<S,T>

的形式提供回调
public class EditingCell<S,T> extends TableCell<S,T> {

    private final BiConsumer<S,T> updater ;

    public EditingCell(BiConsumer<S,T> updater) {
        this.updater = updater ;
    }

    // ....

    // not really sure what this method is for:
    public void commit(T val) {
        S rowValue = getTableView().getItems().get(getIndex());
        updater.accept(rowValue, val);
    }

    // wouldn't this be better?
    @Override
    public void commitEdit(T newValue) {
        super.commitEdit(newValue);
        S rowValue = getTableView().getItems().get(getIndex());
        updater.accept(rowValue, val);
    }

    // ...
}

然后你会做以下事情:

TableView<Person> table = new TableView<>();

TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");
firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
firstNameColumn.setCellFactory(col -> new EditingCell(Person::setFirstName));

答案 1 :(得分:0)

挖掘后,我发现了如何获取列的属性名称。随后我继续写了一些通用的反思来强制更新。为了方便起见,我用方法commit(Object val)包装了所有内容。这些是对使用hereEditCell类的修改。

免责声明:仅当您使用PropertyValueFactory并遵循行类中的命名约定时,此方法才有效。这也是非常易变的代码,由您自行决定使用和修改。

我将单元格修改为public static class EditingCell<S, T> extends TableCell<S, T>的通用单元格。教程中的其他内容应该仍然相同,如果没有随时告诉我,我会在此更新。

public void commit(Object val) {

        // Get the table
        TableView<S> t = this.getTableView();

        // Get the selected row/column
        S selectedRow = t.getItems().get(this.getTableRow().getIndex());
        TableColumn<S, ?> selectedColumn = t.getColumns().get(t.getColumns().indexOf(this.getTableColumn()));

        // 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);
    }

然后由于文本字段不会更新,我在cancelEdit()强制对其进行更新。这稍微特定于我的情况(我希望默认值为0.0,只有接受的值是双倍的) - 根据需要修改它。

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

    // Default value
    String val = "0.0";

    // Check to see if there's a value
    if (!textField.getText().equals(""))
        val = textField.getText();

    // Set table cell text
    setText("" + val);
    setGraphic(null);
}