【问题标题】:JavaFX: Bind List<A> bidirectional to List<B> throws StackOverflowErrorJavaFX:将 List<A> 双向绑定到 List<B> 会引发 StackOverflowError
【发布时间】:2017-08-12 10:48:24
【问题描述】:

我正在尝试绑定两个ListProperties 双向。问题是,它们有不同的类型(A 和 B)。

Test4#test01() 说明了我想做的事情。

Test4#test02() 是我这样做的幼稚方法,但这会导致StackOverflowError

如何使用给定的 AB 变压器和 BA 变压器将List&lt;A&gt; 双向绑定到List&lt;B&gt; 这是一个 MWE:

public class Test4 {

    public Test4() {

    }

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

    class A {
    @Override
    public boolean equals(final Object obj) {
        return obj instanceof A;
    }
    }

    class B {
    @Override
    public boolean equals(final Object obj) {
        return obj instanceof B;
    }
    }

    ListProperty<A> listA = new SimpleListProperty<>(FXCollections.observableArrayList());

    ListProperty<B> listB = new SimpleListProperty<>(FXCollections.observableArrayList());

    Function<A, B> trivialTransformerAB = a -> new B();

    Function<B, A> trivialTransformerBA = b -> new A();

    ListChangeListener<A> listAListener;

    ListChangeListener<B> listBListener;

    @Test
    public void test01() {
    // Bindings.bindContentBidirectional(listA, listB,
    // trivialTransformerAB, trivialTransformerBA);
    }

    @Test
    public void test02() {
    listAListener = c -> {
        while (c.next()) {
        if (c.wasRemoved() || c.wasUpdated()) {
            c.getList().subList(c.getFrom(), c.getTo())
                .forEach(a -> listB.remove(trivialTransformerAB.apply(a)));
        }
        if (c.wasAdded() || c.wasUpdated()) {
            c.getList().subList(c.getFrom(), c.getTo()).forEach(a -> {
            final B b = trivialTransformerAB.apply(a);
            if (!listB.contains(b)) {
                listB.add(trivialTransformerAB.apply(a));
            }
            });
        }
        }
    };
    listBListener = c -> {
        while (c.next()) {
        if (c.wasRemoved() || c.wasUpdated()) {
            c.getList().subList(c.getFrom(), c.getTo())
                .forEach(b -> listA.remove(trivialTransformerBA.apply(b)));
        }
        if (c.wasAdded() || c.wasUpdated()) {
            c.getList().subList(c.getFrom(), c.getTo()).forEach(b -> {
            final A a = trivialTransformerBA.apply(b);
            if (!listA.contains(a)) {
                listA.add(trivialTransformerBA.apply(b));
            }
            });
        }
        }
    };
    listA.addListener(listAListener);
    listB.addListener(listBListener);

    listA.add(new A());
    assertThat(listB.size(), is(1));
    }

}

错误:

java.lang.StackOverflowError
    at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031)
    at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031)
[..]

【问题讨论】:

    标签: java javafx data-binding stack-overflow


    【解决方案1】:

    您设置侦听器的方式造成了无限循环。

    我建议在这两行中分别设置一个断点并使用调试器逐步执行:

    listB.add(trivialTransformerAB.apply(a));
    
    listA.add(trivialTransformerBA.apply(b));
    

    【讨论】:

      猜你喜欢
      • 2019-12-09
      • 2019-10-23
      • 2018-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 2021-04-03
      相关资源
      最近更新 更多