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.pet...@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.mik...@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