为什么与lambda等效的CheckBoxTableCell的setSelectedStateCallback无法在JavaFX8中编译?

时间:2018-10-06 07:02:35

标签: javafx lambda callback javafx-8

一个相对的Java新手问题。

我正尝试解决CheckBoxTableCell遇到的另一个问题,并遇到了这篇文章:CheckBoxTableCell changelistener not working

在尝试用户James_D的示例时,我尝试将setSelectedStateCallback转换为lambda表达式。但是,它没有编译并生成“ lambda表达式中的参数类型不兼容”错误。

原始代码如下:

cbCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
    @Override
    public ObservableValue<Boolean> call(Integer index) {
        return selected;
    }
});

NetBeans 8.2将其转换为此:

cbCell.setSelectedStateCallback((Integer index) -> selected);

然后我在这篇帖子Call Back Lambda Expressions + JavaFX中遵循了fabian用户的回答,手动编写了lambda并最终得到了同样的结果。

为什么lambda表达式不能编译?应该如何编写使其能够编译?

如果有帮助,这里是一个MVCE,其中包含原始代码和lambda等效代码。

我正在使用JavaFX8(JDK1.8.0_181)。

package test26;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class Test26 extends Application {

    private Parent createContent() {

        TableView<TestModel> table = new TableView<>();
        ObservableList<TestModel> olTestModel = FXCollections.observableArrayList(testmodel -> new Observable[] {
                testmodel.checkboxProperty()
        });
        olTestModel.add(new TestModel(false));
        table.setItems(olTestModel);

        TableColumn<TestModel, Boolean> colCheckbox = new TableColumn<>("checkbox");

        colCheckbox.setCellValueFactory(cellData -> cellData.getValue().checkboxProperty());

        colCheckbox.setCellFactory((TableColumn<TestModel, Boolean> cb) -> {

            final CheckBoxTableCell cbCell = new CheckBoxTableCell<>();
            final BooleanProperty selected = new SimpleBooleanProperty();

            //Original code ...
            cbCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
                @Override
                public ObservableValue<Boolean> call(Integer index) {
                    return selected;
                }
            });

            //... and lambda equivalent that doesn't compile
            cbCell.setSelectedStateCallback((Integer index) -> selected);

            return cbCell;
        });

        table.getSelectionModel().setCellSelectionEnabled(true);
        table.setEditable(true);
        table.getColumns().add(colCheckbox);
        BorderPane content = new BorderPane(table);

        return content;

    }

    public class TestModel {

        private BooleanProperty checkbox;
        public TestModel() {
            this(false);
        }
        public TestModel(
            boolean checkbox
        ) {
            this.checkbox = new SimpleBooleanProperty(checkbox);
        }
        public Boolean getCheckbox() {
            return checkbox.get();
        }
        public void setCheckbox(boolean checkbox) {
            this.checkbox.set(checkbox);
        }
        public BooleanProperty checkboxProperty() {
            return checkbox;
        }

    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setTitle("Test");
        stage.setWidth(500);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

1 个答案:

答案 0 :(得分:1)

这里的问题是,您在此声明中使用了原始类型,因此它期望Object不是Integer。但是您在此处显式传递了一个Integer,从而导致错误。

final CheckBoxTableCell cbCell

一种快速而肮脏的解决方法

cbCell.setSelectedStateCallback(index -> selected);

在上述情况下,编译器会将类型推断为Object,因为没有明确给出。但这会给您一个未经检查的警告。因此,从长远来看,请使用通用类型而不是原始类型。

像下面一样参数化CheckBoxTableCell的声明,它将修复代码中所有未检查的警告。因此,这将节省生命。

final CheckBoxTableCell<TestModel, Boolean> cbCell = new CheckBoxTableCell<>();

然后将您的代码改回您最初使用的形式,

cbCell.setSelectedStateCallback((Integer index) -> selected);

请注意,现在没有任何编译错误。然后删除类型Integer,让编译器进行推断。