监听JavaFX中列表内对象的变化,与监听列表本身的变化相对立。

huangapple go评论74阅读模式
英文:

Listening to Object changes within a List in JavaFX, in contrast to listening to List changes itself

问题

以下代码段监听rectangles(一个矩形列表)中的更改,并在每次将Rectangle对象添加到rectangles或从中移除时在屏幕上打印event is invoked.

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

    }
}

我的回答是:是可能监听rectangles中对象的更改,而不仅仅是监听添加到或移除自rectangles中的情况。但是,你需要实现自定义的监听器,以便在Rectangle对象的属性发生变化时触发事件。以下是一个示例,你可以参考它来实现你的需求:

import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
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((Change<? extends Rectangle> change) -> {
            while (change.next()) {
                if (change.wasUpdated()) {
                    System.out.println("Event is invoked. Rectangle properties changed.");
                }
            }
        });

        rectangles.addAll(rectangle);

        // Simulate a property change in a Rectangle
        SimpleObjectProperty<Color> fillColorProperty = (SimpleObjectProperty<Color>) rectangle.fillProperty();
        fillColorProperty.set(new Color(1, 0, 0, 0.5));
    }
}

在这个示例中,我们通过监听fillProperty()的变化来检测Rectangle的填充颜色属性是否发生了变化。这样,当你更改Rectangle对象的填充颜色时,会触发事件。

英文:

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&lt;Rectangle&gt; rectangles = FXCollections.observableArrayList();
        rectangles.addListener((ListChangeListener&lt;Rectangle&gt;) change -&gt;
                System.out.println(&quot;event is invoked.&quot;));

        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&lt;Rectangle&gt; rectangles = FXCollections.observableArrayList();
        rectangles.addListener((ListChangeListener&lt;Rectangle&gt;) change -&gt;
                System.out.println(&quot;event is invoked.&quot;));

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

    }
}

答案1

得分: 3

您可以创建一个ObservableList,当列表元素的属性发生更改时,它会向监听器触发更改事件,方法是在创建列表时指定一个提取器

提取器是一个函数,将列表的每个元素映射到应该监听更改的Observable值数组。如果您想要知道列表中矩形的fill属性何时更改,可以这样做:

public class Test2 {

    public static void main(String[] args) {

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

        // 创建带有提取器的列表:
        ObservableList<Rectangle> rectangles = 
            FXCollections.observableArrayList(rect -> new Observable[] { rect.fillProperty() });

        rectangles.addListener((ListChangeListener.Change<? extends Rectangle> change) ->
                System.out.println("事件被触发。"));

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

    }
}

请参考ListChangeListener.Change API文档以获取有关change对象上的方法,这些方法允许您确定何种原因导致监听器被调用。例如:

rectangles.addListener((ListChangeListener.Change<? extends Rectangle> change) -> {
    while (change.next()) {
        if (change.wasAdded()) {
            System.out.println("已添加 " + change.getAddedSize() + " 个矩形");
        }
        if (change.wasRemoved()) {
            System.out.println("已删除 " + change.getRemovedSize() + " 个元素");
        }
        if (change.wasUpdated()) {
            int from = change.getFrom();
            int to = change.getTo();
            System.out.println("从索引 " + from + " 到 " + to + " 的矩形已更改");
        }
    }
});

将生成以下输出:

已添加 1 个矩形
从索引 0 到 1 的矩形已更改
英文:

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&lt;Rectangle&gt; rectangles = 
            FXCollections.observableArrayList(rect -&gt; new Observable[] { rect.fillProperty()});

        rectangles.addListener((ListChangeListener.Change&lt;? extends Rectangle&gt; change) -&gt;
                System.out.println(&quot;event is invoked.&quot;));

        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&lt;? extends Rectangle&gt; change) -&gt; {
        while (change.next()) {
            if (change.wasAdded()) {
                System.out.println(&quot;Added &quot; + change.getAddedSize() + &quot; rectangle(s)&quot;);
            }
            if (change.wasRemoved()) {
                System.out.println(&quot;Removed &quot;+change.getRemovedSize()+&quot; element(s)&quot;);
            }
            if (change.wasUpdated()) {
                int from = change.getFrom();
                int to = change.getTo();
                System.out.println(&quot;Rectangle(s) from index &quot;+from+&quot; to &quot;+to+&quot; were changed&quot;);
            }
        }
    });

will generate the following output:

Added 1 rectangle(s)
Rectangle(s) from index 0 to 1 were changed

huangapple
  • 本文由 发表于 2023年6月19日 13:36:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76503847.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定