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
我试图让程序在 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