Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX ReadOnlyListProperty not read only?

Tags:

javafx

This code throws an UnsupportedOperationException, as I would expect it to since it's read only.

ListProperty<String> lp = new SimpleListProperty<String>();
ReadOnlyListWrapper<String> rolw = new ReadOnlyListWrapper<String>(lp);
ReadOnlyListProperty<String> rolp = rolw.getReadOnlyProperty();
rolp.add("element");

However, this code does not.

ObservableList<String> ol = FXCollections.observableArrayList();
ReadOnlyListWrapper<String> rolw = new ReadOnlyListWrapper<String>(ol);
ReadOnlyListProperty<String> rolp = rolw.getReadOnlyProperty();
rolp.add("element");

Is this a bug, or am I just not understanding something?

like image 424
Tim Fletcher Avatar asked Sep 03 '13 15:09

Tim Fletcher


1 Answers

The original expectation is wrong - for the examples provided. The UnsupportedOperationException occurs for a different reason and not because a "read-only" list is being "written" to. It is still possible to have "read-only" lists. I hope the answer below helps clarify.

The answer needs to be considered in two parts. One: The ListProperty exception and Two: Read-Only lists.

1) The ListProperty example fails because no list has been assigned to the property.

This, simplified, example also throws the exception. Note that any "read-only" aspects are removed:

ListProperty<String> lp = new SimpleListProperty<>();
lp.add("element");

This can be corrected with:

ObservableList ol = FXCollections.observableArrayList();
ListProperty<String> lp = new SimpleListProperty<>();
lp.setValue(ol);
lp.add("element");

If we change the original example in a similar manner then neither the ListProperty nor the ObservableList examples will throw an exception, which wasn't what the OP wanted or expected.

2) The second part asks why can an element be added to a read-only list. Using FXCollections.unmodifiableObservableList to create the read-only list will throw UnsupportedOperationException as expected:

ObservableList<String> ol = FXCollections.observableArrayList();
ObservableList<String> uol = FXCollections.unmodifiableObservableList(ol);
uol.add("element");

But this doesn't answer the question why doesn't the ReadOnlyListWrapper/Property do this?

Let's deal with the Property first. ListProperty enable the value to be changed, i.e. it allows you to assign a different list to the property. ReadOnlyListProperty does not allow this, i.e. once a list is assigned it remains that list object. The content of the list can still change. The example below makes no sense with ReadOnlyListProperty:

ObservableList<String> ol1 = FXCollections.observableArrayList();
ObservableList<String> ol2 = FXCollections.observableArrayList();
ListProperty<String> lp = new SimpleListProperty<>(ol1);
lp.setValue(ol2);

So read-only refers to the Property, and not the List.

Finally - ReadOnlyListWrapper - as the API documentation states "This class provides a convenient class to define read-only properties. It creates two properties that are synchronized. One property is read-only and can be passed to external users. The other property is read- and writable and should be used internally only."

like image 151
Nigel Eke Avatar answered Nov 25 '22 10:11

Nigel Eke