findusl
findusl

Reputation: 2644

JavaFX Table view Cell Reuse

I have a javafx application with a TableView. Only the first column (dataTypeColumn) is editable and it contains a ComboBox for editing. Now the TableView does what it is supposed to do, however there is a combination of weird bugs when i start editing a cell and then scroll it out of view without commiting the edit. I am pretty sure it is because of the way TableView reuses the cells. However I haven't found any way to intervene with it, for example to forbid reuse of cells that are currently editing. Can you help me with that.

Even though I am pretty sure it is because of cell reuse, I will write the whole problem below, in case the source of the problem is a different.

The column in question contains Values of the enum DataType I have a cell Factory for that column looking like this:

dataTypeColumn.setCellFactory(param -> new ComboBoxTableCell<>(DataType.values()));

The values for the column get read like this:

dataTypeColumn.setCellValueFactory(param -> Bindings.valueAt(configuration, param.getValue()));

In case this is confusing, the items that I give my TableView are Integers (from 0 to n-1), and in the different column CellValueFactories the actual values will be loaded depending on the Integer assoziated with the current column.

So when editing it, it shows a ComboBox with all the Values that DataType can have and let's the user select one. I have a callback on the column that reacts to the Edit commited event and looks like this:

public void editCommited(TableColumn.CellEditEvent<Integer, DataType> event) {
        //configuration is an ObservableList containing DataType elements
        configuration.set(event.getRowValue(), event.getNewValue());
    }

So about the problems that occur. At the beginning all cells in that column have the same value: "nothing selected". It is a special value of the enum reserved for this case, as I didn't find a setPlaceholder function on the ComboBoxTableCell class. When I know start editing one of the cells and then scroll it out of view, one of the next rows will suddendly be in the editing state as well, even though that row has not been touched before. If I scroll further an cell in the editing state will appear every time the previous one scrolls out of view. I can also go back and will find the same cells in the editing state. If I edit the cell that should not be in the editing state, it will not change, but instead the cell that I originally tried to edit will change it's value. This might be due to the underlying ObservableList, that automatically updates the value in the column.

If I start editing a cell that has a different value (from a previous edit), something even more weird happens. When scrolling it out of view again a new row will have a cell in the editing page, however with the default value "nothing selected". If I scroll backwards the cell that i tried to edit originally will no longer be in the editing state however it's value has changed to "nothing selected". As if the new cell that got the editing state somehow commited it's own value.

Please some help with this :)

Upvotes: 1

Views: 873

Answers (1)

fabian
fabian

Reputation: 82451

This indeed seems to be a bug. Rather surprising, if you move the scroll bar with the mouse, the edit is properly canceled, but not, if you use the mouse wheel to scroll.

You can easily create a workaround for this buf however, since you simply have to cancel the edit, when the item is replaced. You could e.g. use this method to create the cellFactory on your own:

public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> comboBoxCellFactory(ObservableList<T> items) {
    if (items == null) {
        throw new IllegalArgumentException();
    }
    return column -> new ComboBoxTableCell<S, T>(items) {

        @Override
        public void updateIndex(int i) {
            cancelEdit();
            super.updateIndex(i);
        }

    };
}

Upvotes: 3

Related Questions