[ListView] `b.bind(a)` not behaviorally equivalent to `a.addListener(o -> b.set(a.get()))`
Tomas Mikula
tomas.mikula at gmail.com
Mon Dec 16 12:51:19 PST 2013
Never mind,
b.bind(a);
should not be equivalent to
a.addListener(o -> b.set(a.get()));
in the first place, but rather to
a.addListener(o -> b.set(a.get()));
b.set(a.get()); // don't forget this!
When I fixed my example, I'm not observing any difference in behavior.
I'm still not getting the behavior I want, but due to
https://javafx-jira.kenai.com/browse/RT-34897.
Thanks,
Tomas
On Mon, Dec 16, 2013 at 8:37 PM, Anthony Petrov
<anthony.petrov at oracle.com> wrote:
> Filing a bug never hurts. We'll either fix it, or close it and explain why
> it's not a bug then.
>
> --
> best regards,
> Anthony
>
>
> On 12/13/2013 11:17 PM, Tomas Mikula wrote:
>>
>> I guess my main question is: should I file a bug on ListView?
>>
>> Tomas
>>
>> On Fri, Dec 13, 2013 at 8:15 PM, Tomas Mikula <tomas.mikula at gmail.com>
>> wrote:
>>>
>>> I just came across a strange case when these two are not equivalent.
>>> Maybe that is no surprise to you, but it was to me. The case I
>>> stumbled upon most likely has to do with ListView internals.
>>>
>>> Substitute
>>> a := ListView.widthProperty()
>>> b := ListCell.prefWidthProperty()
>>>
>>> and the code that demonstrates the difference:
>>>
>>>
>>> public class Test extends Application {
>>>
>>> private static class MyCell extends ListCell<String> {
>>> public MyCell(ListView<String> lv) {
>>> setMaxWidth(Region.USE_PREF_SIZE);
>>>
>>> // !!! comment out exactly one of the following
>>> // !!! two lines to demonstrate the difference
>>> prefWidthProperty().bind(lv.widthProperty());
>>> lv.widthProperty().addListener(o ->
>>> setPrefWidth(lv.getWidth()));
>>> }
>>>
>>> @Override
>>> protected void updateItem(String item, boolean empty) {
>>> super.updateItem(item, empty);
>>> setGraphic(empty ? null : new TextFlow(new Text(item)));
>>> }
>>> }
>>>
>>> @Override
>>> public void start(Stage stage) {
>>> ListView<String> listView = new ListView<>();
>>> listView.setCellFactory(lv -> new MyCell(lv));
>>> listView.getItems().add("This is a very long line that needs
>>> to be wrapped");
>>>
>>> StackPane stack = new StackPane();
>>> stack.getChildren().add(listView);
>>> Scene scene = new Scene(stack, 200, 100);
>>> stage.setScene(scene);
>>> stage.show();
>>> }
>>>
>>> public static void main(String[] args) {
>>> launch(args);
>>> }
>>> }
>>>
>>>
>>> When I run the "bind" version, the text shows up wrapped.
>>> When I run the "addListener" version, the text shows up in one long line.
>>>
>>> Do you think this is a bug in ListView, or is there a reasonable
>>> explanation?
>>>
>>> Just for the record, I consider the "wrapping" behavior to be the correct
>>> one.
>>>
>>>
>>> My *speculation* about the possible cause follows:
>>>
>>> The only case I could come up with when
>>> A) b.bind(a)
>>> and
>>> B) a.addListener(o -> b.set(a.get()))
>>> are effectively different is when both of these conditions hold:
>>> 1) there is an invalidation listener set on b that causes b to become
>>> valid (e.g. calls b.get()); and
>>> 2) a is invalidated twice in a row, but recomputes to the same value each
>>> time.
>>>
>>> Now the scenarios for A) and B) differ:
>>>
>>> Scenario A (b.bind(a)):
>>> - a is invalidated for the first time
>>> - b's invalidation listener is called for the first time
>>> - b is now valid
>>> - a is invalidated for the second time
>>> - b's invalidation listener is called for the *SECOND* time
>>>
>>> Scenario B (a.addListener(o -> b.set(a.get()))):
>>> - a is invalidated for the first time
>>> - b is set to a.get() = x and b's invalidation listener is called for
>>> the first time
>>> - b is now valid
>>> - a is invalidated for the second time
>>> - b is set to a.get() = x and b's invalidation listener is *NOT*
>>> called for the second time, because b's value did not change
>>>
>>> In scenario A, b's invalidation listener is called twice, while in
>>> scenario B just once. If "weird things" are happening in this
>>> invalidation listener, this can result in different behavior.
>>>
>>> Now, if b is ListCell.prefWidthProperty(), scenario A and scenario B
>>> cause it to be invalidated different number of times, which, my
>>> *speculation*, could yield different behavior.
>>> This is how far I got.
>>>
>>> Cheers,
>>> Tomas
More information about the openjfx-dev
mailing list