0

The following code snippet listen to changes in rectangles (a list of rectangles ) and prints event is invoked. on screen whenever a Rectangle object is added to or removed from rectangles.

import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class test2 {

    public static void main(String[] args) {

        Rectangle rectangle=new Rectangle(0,0,1,1);

        ObservableList<Rectangle> rectangles = FXCollections.observableArrayList();
        rectangles.addListener((ListChangeListener<Rectangle>) change ->
                System.out.println("event is invoked."));

        rectangles.addAll(rectangle);

    }
}

My question is whether it is possible to listen to changes in the objects in rectangles rather than listening to adding to or removing from rectangles. For example, the event should be invoked when I change the fill color of a Rectangle object in rectangles. I tried the following code (added a line of rectangle.setFill(new Color(1,0,0,0.5));) and expected to have event is invoked. printed twice, but it did not work.

import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class test2 {

    public static void main(String[] args) {

        Rectangle rectangle=new Rectangle(0,0,1,1);

        ObservableList<Rectangle> rectangles = FXCollections.observableArrayList();
        rectangles.addListener((ListChangeListener<Rectangle>) change ->
                System.out.println("event is invoked."));

        rectangles.addAll(rectangle);
        rectangle.setFill(new Color(1,0,0,0.5));

    }
}
Keen Teen
  • 25
  • 4
  • You can add a [listener](https://stackoverflow.com/questions/43393423/how-to-make-javafx-property-listener-to-fire-an-event-even-if-the-oldvaule-and-n) to any [JavaFX] property. Refer to the [documentation](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/shape/Rectangle.html) for the properties of `Rectangle`. – Abra Jun 19 '23 at 06:07
  • 1
    Create the list with an [extractor](https://openjfx.io/javadoc/20/javafx.base/javafx/collections/FXCollections.html#observableArrayList(javafx.util.Callback)). – James_D Jun 19 '23 at 12:52

1 Answers1

3

You can create an ObservableList that fires change events to listeners when properties in the list's elements are changed by specifying an extractor when you create the list.

The extractor is a function which maps each element of the list to an array of Observable values which should be listened to for changes. If you want to know when the fill property of the rectangle in your list changes, you can do:

public class Test2 {

    public static void main(String[] args) {

        Rectangle rectangle=new Rectangle(0,0,1,1);

        // create list with an extractor:
        ObservableList<Rectangle> rectangles = 
            FXCollections.observableArrayList(rect -> new Observable[] { rect.fillProperty()});

        rectangles.addListener((ListChangeListener.Change<? extends Rectangle> change) ->
                System.out.println("event is invoked."));

        rectangles.addAll(rectangle);
        rectangle.setFill(new Color(1,0,0,0.5));

    }
}

Refer to the ListChangeListener.Change API documentation for methods on the change object that allow you to determine what caused the listener to be invoked. For example:

    rectangles.addListener((ListChangeListener.Change<? extends Rectangle> change) -> {
        while (change.next()) {
            if (change.wasAdded()) {
                System.out.println("Added " + change.getAddedSize() + " rectangle(s)");
            }
            if (change.wasRemoved()) {
                System.out.println("Removed "+change.getRemovedSize()+" element(s)");
            }
            if (change.wasUpdated()) {
                int from = change.getFrom();
                int to = change.getTo();
                System.out.println("Rectangle(s) from index "+from+" to "+to+" were changed");
            }
        }
    });

will generate the following output:

Added 1 rectangle(s)
Rectangle(s) from index 0 to 1 were changed
James_D
  • 201,275
  • 16
  • 291
  • 322