TableView 的 ItemProperty() 的侦听器不会失效(javafx)?

Listeners of ItemProperty() of TableView don't get invalidated (javafx)?

我试图让程序在 TableView 中添加一行时做出反应,但 ItemProperty 不会在列表更改时通知侦听器。

我认为这可能是因为我没有 'set' 项目(作为新的 不同 列表)而只是添加到列表中,但我不确定。

我在 Whosebug 上找到了 this,但我认为这不是同一个问题(或者至少解决方案对我不起作用)。

有什么方便的方法可以解决这个问题吗?

最小可重现示例:

import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.Random;

public class Main extends Application {

    private static Random RG = new Random();

    @Override
    public void start(Stage stage) throws Exception {
        VBox vBox = new VBox();

        TableView<Integer> integerTableView = new TableView<>();
        TableColumn<Integer, Integer> testColumn = new TableColumn<>("test");
        testColumn.setCellValueFactory(i -> new SimpleIntegerProperty(i.getValue().intValue()).asObject());

        integerTableView.getColumns().add(testColumn);

        Button button = new Button("Add random number");
        button.setOnAction(e -> {
            integerTableView.getItems().add(RG.nextInt());
        });

        vBox.getChildren().addAll(integerTableView, button);
        Scene scene = new Scene(vBox);
        stage.setScene(scene);
        stage.show();

        integerTableView.itemsProperty().addListener(e -> System.out.println("Added item"));
    }

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

问题与解决方案

您正在将 InvalidationListener 添加到 items 属性,这是 ObjectProperty 的一个实例。 属性 上的侦听器将不知道它包含的值何时发生变化(它甚至不知道 if/when 它的值是可观察的)。您需要将侦听器添加到 ObservableList 本身。

// javafx.beans.Observable
integerTableView
    .getItems()
    .addListener((Observable e) -> System.out.println("Items invalidated!"));

ListChangeListener

请注意,ObservableList 上的 InvalidationListener 将因对列表所做的任何类型的更改而被触发,并且您不会知道进行了何种更改。如果您想了解有关更改的详细信息,那么您应该使用 ListChangeListener.

// javafx.collections.ListChangeListener
integerTableView.getItems().addListener((ListChangeListener<Integer>) c -> {
  while (c.next()) {
    // process change (see documentation for more info)
  }
});

替换

integerTableView.itemsProperty().addListener(e -> System.out.println("Added item"));}

由此

integerTableView.getItems().addListener((ListChangeListener )(e -> {System.out.println("Added item");}));

!!!!你需要投射 lambda (ListChangeListener) 否则你会得到“对 addlistener 的引用不明确”警告,因为有更多的听众 Class