Home > Back-end >  Listeners of ItemProperty() of TableView don't get invalidated (javafx)?
Listeners of ItemProperty() of TableView don't get invalidated (javafx)?

Time:04-18

I'm trying to let a program react when a line is added in a TableView, but the ItemProperty doesn't notify the listeners when the list is changed.

I think that might be because I don't 'set' the items (as a new different list) but just add to the list, but I'm not sure.

I found this on stackoverflow, but I don't think it's the same problem (or at least the solution didn't work for me).

Is there any convenient way to fix this?

minimal reproducible example:

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);
    }
}

CodePudding user response:

You're adding the InvalidationListener to the items property, which is an instance of ObjectProperty. A listener on that property will not know when something happens to the value it contains (it doesn't even know if/when its value is observable). You need to add the listener to the ObservableList itself.

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

Based on your example code, you'd need to add:

import javafx.beans.Observable;

To your code.

Note if you replace the list (e.g., integerTableView.setItems(newList)) then you'll need to add a listener to the new list to continue getting notified of the table's items being invalidated.

CodePudding user response:

replace

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

by this

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

!!!! you need to cast lambda (ListChangeListener ) otherwise you will get "reference to addlistener is ambiguous " warning , because there are more listeners for that Class

  • Related