How to prevent TableView from doing TableColumn re-order in javaFX 8?
An alternative solution which does not require use of private API in Java 8.
public static <T> void preventColumnReordering(TableView<T> tableView) {
Platform.runLater(() -> {
for (Node header : tableView.lookupAll(".column-header")) {
header.addEventFilter(MouseEvent.MOUSE_DRAGGED, Event::consume);
}
});
}
I know the question tagged java-8
but for those who wander along, In Java 9
all above codes would break because of modularity which make .sun
package inaccessible and removal of impl_
. Despite these changes, it introduces convenient public methods that you can use which are:
setReorderable(boolean value)
getReorderable()
for TableColumnBase
such as TableColumn
to be used for set Reorderable,
Spent half of a day trying to solve the problem. Maybe my investigation can be useful for someone else. It's possible to disable column reordering using some hacks. And here're the steps:
- Get table header. This can be done as described here: https://stackoverflow.com/a/12465155
- Add change event listener to reorderingProperty which sets reordering back to false.
Full code is here:
tableView.widthProperty().addListener(new ChangeListener<Number>()
{
@Override
public void changed(ObservableValue<? extends Number> source, Number oldWidth, Number newWidth)
{
TableHeaderRow header = (TableHeaderRow) tableView.lookup("TableHeaderRow");
header.reorderingProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
header.setReordering(false);
}
});
}
});
I'm not sure about side effects of this solution, but quick tests show that solution works well.
I like the idea from Alexander Chingarev but I think the code will produce memory leaks! Every time the width property changes a new listener is registered and older listeners are never garbage collected! So you can either store a reference to the listener and make sure to remove it from the observable value (in this case the reordering property) before adding a new listener or you make sure the listener is only added once to the reordering property.
I used the skin property which only changes once (if I'm not mistaken) to add my listener:
tableView.skinProperty().addListener((obs, oldSkin, newSkin) -> {
final TableHeaderRow header = (TableHeaderRow) lookup("TableHeaderRow");
header.reorderingProperty().addListener((o, oldVal, newVal) -> header.setReordering(false));
});