TableView,用于定义自定义编辑行为的不兼容类型

TableView, incompatible types for defining custom editing behaviour

(我有点摸不着头脑,所以如果我写的不够清楚,请多多包涵。)

我有一个数据模型,用作我的 TableView 的数据。 DataModel 包含名称、姓氏、年龄和电话的字符串和整数数据。数字。

public class DataModel {
   private SimpleStringProperty sName;
   private SimpleStringProperty sSurname;
   private SimpleIntegerProperty iAge;
   private SimpleIntegerProperty iPhoneNumber;

   public DataModel(String sName, String sSurname, int iAge, int iPhoneNumber) {
      this.sName = new SimpleStringProperty(sName);
      this.sSurname = new SimpleStringProperty(sSurname);
      this.iAge = new SimpleIntegerProperty(iAge);
      this.iPhoneNumber = new SimpleIntegerProperty(iPhoneNumber);
   }
//...getters and setters..

当我使用 EditingCell 进行自定义单元格编辑事件时 class(如此处所述 Oracle Tutorial ) 它适用于 DataModel 的 SimpleStringProperties 而不适用于 SimpleIntegerValues:

    Callback<TableColumn<DataModel, String>, TableCell<DataModel, String>> cellFactory = (TableColumn<DataModel, String> p) -> new EditingCell();

    surnameColumn.setCellFactory(TextFieldTableCell.<DataModel>forTableColumn());
    surnameColumn.setCellFactory(cellFactory);
    surnameColumn.setOnEditCommit((CellEditEvent<DataModel, String> event) -> {
        ((DataModel) event.getTableView().getItems(). get(event.getTablePosition().getRow())).  setsSurname(event.getNewValue());
    });
    ageColumn.setCellFactory(TextFieldTableCell.<DataModel, Integer>forTableColumn(new IntegerStringConverter()));
X   ageColumn.setCellFactory(cellFactory); //dodajemy custom editing event
XX  ageColumn.setOnEditCommit((CellEditEvent<DataModel, Integer> event) -> {
    ((DataModel) event.getTableView().getItems(). get(event.getTablePosition().getRow())).  setiAge(event.getNewValue());
    });

X 是编译器向我发送错误的地方:

The method setCellFactory(Callback<TableColumn<DataModel,Integer>,TableCell<DataModel,Integer>>) in the type TableColumn<DataModel,Integer> is not applicable for the arguments (Callback<TableColumn<DataModel,String>,TableCell<DataModel,String>>)

XX 是编译器向我发送错误的地方:

The method setOnEditCommit(EventHandler<TableColumn.CellEditEvent<DataModel,Integer>>) in the type TableColumn<DataModel,Integer> is not applicable for the arguments ((CellEditEvent<DataModel, Integer> event) -> {})

互联网上似乎没有太多关于使用 TableView 的资料。除了上面的这些错误,我想知道是否最好只对数据使用 SimpleStringProperties Class 然后再做一些转换?

编辑: 这是 EditingCell 的实现。

package application;

import javafx.beans.value.ObservableValue;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;

//Klasa ta pozwala na definiowania zachowania komórek, które edytuje użytkownik
public class EditingCell extends TableCell<DataModel, String>{ 
private TextField textField;

public EditingCell() {
}

@Override
public void startEdit() {
    if (!isEmpty()) {
        super.startEdit();
        createTextField();
        setText(null);
        setGraphic(textField);
        textField.selectAll();
    }
}

@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(
        (ObservableValue<? extends Boolean> arg0, 
        Boolean arg1, Boolean arg2) -> {
            if (!arg2) {
                commitEdit(textField.getText());
            }
    });
}

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

}

我认为第二个错误 (ageColumn.setOnEditCommit(...)) 只是由于第一个错误而出现在您的 IDE 中。当我自己尝试时,它对我来说效果很好。

我无法重现第一个错误,因为你没有 post EditingCell;但是你显然在这里有不匹配的类型。 TableColumn<S,T> 定义了一个 setCellFactory(Callback<TableColumn<S,T>, TableCell<S,T>>) 方法。对于你的 ageColumn,类型是 S=DataModelT=Integer,所以你需要传递一个 Callback<TableColumn<DataModel, Integer>, TableCell<DataModel, Integer>>,这不是你为 cellFactory 声明的类型.我假设 EditingCellTableCell<String> 的子 class(否则 cellFactory 的声明将无法编译)。您需要创建另一个 class(比如 AgeCell),它是 TableCell<Integer> 的子 class,然后执行

Callback<TableColumn<DataModel, Integer>, TableCell<DataModel, Integer>> ageCellFactory = (TableColumn<DataModel, Integer> col) -> new AgeCell();

根据您的 EditingCell 的实现方式,以及您需要对单元格中的对象类型了解多少,您可以将其设为通用 class:

public class EditingCell<T> extends TableCell<DataModel, T> {
    @Override
    public void updateItem(T item, boolean empty) {
        // ...
    }

    // ...
}

然后你可以做

surnameCol.setCellFactory(column -> new EditingCell<String>());
ageCol.setCellFactory(column -> new EditingCell<Integer>());

在不了解您的 EditingCell 实现的情况下,很难知道这是否是一个可行的选择。 EditingCell 可能需要传递 StringConverter<T> 以将值从 TextField 转换为要提供给 DataModel 的值,并将数据模型值转换为值待展示。

I wonder is it best generaly to use only SimpleStringProperties for Data Class and later just do some conversions?

绝对不是。 JavaFX 中的所有内容(几乎)都设置为通用的,因此您应该利用这一点并在数据模型中使用适当的类型。