How to sort a JavaFX ListProperty

580 Views Asked by At

it seems I have encountered a problem with ListProperties. ObservableLists implement the marker interface SortableList that allows them to be sorted efficiently, firing only a single event. ListProperties do not implement this interface (how could they...?). Instead they use the default implementation of the List interface, firing a lot of changes.

The only solution I can see would be to call sort() on the underlying List directly. But this collides with the scheme of returning the Property itself:

public ObservableList getSomeList()
{
    return someListProperty();
}

which ensures that ListChangeListener remain registered when the underlying List is exchanged.

I would be happy to get some input, maybe I missed something?

1

There are 1 best solutions below

1
On

I guess the SortableList you refer to is the one used in FXCollections.sort.

ListProperty could implement the SortableList interface.

It may indeed be a good idea, since this would allow you to choose the way the wrapped list is sorted, if e.g. FXCollections.sort is used on the property. You could use FXCollections.sort on the contained list in this case.

How could they? Like this:

class MyListProperty<T> extends ListPropertyBase<T> implements SortableList<T> {

    ...

    @Override
    public void sort() {
        ObservableList<T> list = getValue();
        if (list != null) {
            FXCollections.sort((ObservableList<Comparable>) list);
        }
    }

    @Override
    public void sort(Comparator<? super T> comparator) {
        ObservableList<T> list = getValue();
        if (list != null) {
            FXCollections.sort(list, comparator);
        }
    }

}

The only problem is, that SortableList is inside the com.sun.javafx.collections package (see It is a bad practice to use Sun's proprietary Java classes?).

About your collision with the property scheme: there is none, if you define the property the intended way, see Using JavaFX Properties and Binding section Understanding Properties

The property would be implemented like this:

private final ListProperty<MyClass> someList = ...;

public ObservableList<MyClass> getSomeList() {
    return someList.get();
}

public void setSomeList(ObservableList<MyClass> newList) {
    someList.set(newList);
}

public ListProperty<MyClass> someListProperty() {
    return someList;
}

The ListProperty has to ensure the ListChangeListeners registered to it receive the change events from the wrapped list.

Maybe you got confused with readonly list properties used in fxml, but a ListProperty is not readonly.

You could still use this property in a fxml file, but you'd need to use a value of type ObservableList:

<!-- imports -->

<ContainingClass xmlns:fx="http://javafx.com/fxml/1">
    <someList>
        <FXCollections fx:factory="observableArrayList">
            <!-- list content goes here -->
        </FXCollections>
    </someList>
</ContainingClass>