Приложение JavaFX не может скомпилировать лямбда-выражение - PullRequest
0 голосов
/ 21 февраля 2020

Я пытаюсь создать приложение JavaFX для отображения TreeTableView. Все еще настраиваю все это. Я заставил его работать только с одним столбцом без класса Product, но я изо всех сил стараюсь заставить его работать с классом Product и двумя столбцами. Следующий фрагмент кода не компилируется:

 col1.setCellValueFactory(
            (TreeTableColumn.CellDataFeatures<Product, String> param) -> param.getValue().getValue().getNameProperty());

и выдает эту ошибку:

Error:(38, 121) java: incompatible types: bad return type in lambda expression
java.lang.String cannot be converted to javafx.beans.value.ObservableValue<java.lang.String>

Это весь код:

public class Controller implements Initializable {

    @FXML
    private TreeTableView<Product> tableView;
    @FXML
    private TreeTableColumn<Product, String> col1;
    @FXML
    private TreeTableColumn<Product, String> col2;

    TreeItem<Product> product1 = new TreeItem<>(new Product("Bread", "300g"));
    TreeItem<Product> product2 = new TreeItem<>(new Product("Eggs", "5"));
    TreeItem<Product> product3 = new TreeItem<>(new Product("Brad Pitt", "One and Only one"));
    TreeItem<Product> product4 = new TreeItem<>(new Product("Moisturizer", "20"));
    TreeItem<Product> product5 = new TreeItem<>(new Product("Horse Lubricant", "4"));

    TreeItem<Product> root = new TreeItem<>(new Product("Name", "Quantity"));

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        root.getChildren().setAll(product1, product2, product3, product4, product5);

        col1.setCellValueFactory(
                (TreeTableColumn.CellDataFeatures<Product, String> param) -> param.getValue().getValue().getNameProperty());
        col2.setCellValueFactory(
                (TreeTableColumn.CellDataFeatures<Product, String> param) -> param.getValue().getValue().getQuantityProperty());

        tableView.setRoot(root);
        tableView.setShowRoot(false);
    }

    public class Product{
        SimpleStringProperty nameProperty;
        SimpleStringProperty quantityProperty;

        public Product(String name, String quantity){
            this.nameProperty = new SimpleStringProperty(name);
            this.quantityProperty = new SimpleStringProperty(quantity);
        }

        public String getNameProperty() {
            return nameProperty.get();
        }

        public SimpleStringProperty namePropertyProperty() {
            return nameProperty;
        }

        public void setNameProperty(String nameProperty) {
            this.nameProperty.set(nameProperty);
        }

        public String getQuantityProperty() {
            return quantityProperty.get();
        }

        public SimpleStringProperty quantityPropertyProperty() {
            return quantityProperty;
        }

        public void setQuantityProperty(String quantityProperty) {
            this.quantityProperty.set(quantityProperty);
        }
    }
}

1 Ответ

3 голосов
/ 21 февраля 2020

Во-первых, ваш Product класс не обычный. Обычно имя поля соответствует имени свойства (например, name, а не nameProperty). Затем вы называете свой метод get, setter и property в качестве имени свойства. Например:

import javafx.beans.property.StringProperty;
import javafx.beans.property.SimpleStringProperty;

public class Product {

  private final StringProperty name = new SimpleStringProperty(this, "name");
  public final void setName(String name) { this.name.set(name); }
  public final String getName() { return name.get(); }
  public final StringProperty nameProperty() { return name; }

  private final StringProperty quantity = new SimpleStringProperty(this, "quantity");
  public final void setQuantity(String quantity) { this.quantity.set(quantity); }
  public final String getQuantity() { return quantity.get(); }
  public final StringProperty quantityProperty() { return quantity; }

  public Product() {} // typically Java(FX)Beans provide no-arg constructors as well

  public Product(String name, String quantity) {
    setName(name);
    setQuantity(quantity);
  }
}

Примечание: Ваш класс не вложенный c вложенный (т. Е. Внутренний) класс. Это означает, что каждому экземпляру Product требуется экземпляр включающего класса. Если вы хотите оставить Product вложенным классом, рассмотрите возможность сделать его классом c. В моем примере выше предполагается, что Product находится в его собственном исходном файле.

С помощью этого класса вы можете определить фабрики значений ячеек следующим образом:

TreeTableColumn<Product, String> nameCol = ...;
nameCol.setCellValueFactory(data -> data.getValue().getValue().nameProperty());

TreeTableColumn<Product, String> quantityCol = ...;
quantityCol.setCellValueFactory(data -> data.getValue().getValue().quantityProperty());

Примечание фабрики возвращают соответствующее свойство экземпляра Product. Это решает вашу ошибку компиляции, поскольку StringProperty является экземпляром ObservableValue<String>. Это также означает, что ваша таблица имеет прямой доступ к свойству вспомогательной модели, что помогает поддерживать актуальность таблицы, а также реализовывать встроенное редактирование. фабрика значений nameCol с использованием анонимного класса, который явно показывает все используемые типы:

nameCol.setCellValueFactory(new Callback<>() { // may have to explicitly define type arguments, depending on version of Java

  @Override
  public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<Product, String> data) {
    TreeItem<Product> treeItem = data.getValue();
    Product product = treeItem.getValue();
    return product.nameProperty();
  }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...