11

I read this https://bugs.openjdk.java.net/browse/JDK-8102128 but I haven't found something in the Api of JavaFX 8.There isn't any way of prevent reordering in TableView?

geo
  • 2,283
  • 5
  • 28
  • 46

9 Answers9

16

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:

  1. Get table header. This can be done as described here: https://stackoverflow.com/a/12465155
  2. 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.

Community
  • 1
  • 1
10

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,

user33732
  • 101
  • 2
  • 3
8

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));
});
JOpolka
  • 121
  • 1
  • 5
6

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);
        }
    });
}
Adam
  • 35,919
  • 9
  • 100
  • 137
3

The API added in Java 8 RT-24669, is column.impl_setReorderable(false);.

You can see the impl_setReorderable definition in the TableColumnBase.java source.

However, this API is only intended for internal use, marked as deprecated and does not form part of the public JavaFX API.

In general, impl_ methods in JavaFX will be removed at some time in the future, potentially breaking your code at that time if you tried to use them.

In reviewing the code for the implementation of the reorderable property on table columns, it works by ignoring certain mouse events directed to the table column header. Search the TableColumnHeader.java code for isReorderable for more info.

I'm not sure how you would accomplish the exact same behaviour as the impl_setReorderable API using only the public JavaFX API without performing quite a lot of work.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
2

Expanding on a previous contribution I found this

tableView.getColumns().forEach(e -> e.setReorderable(false));

to be very useful in Java 13.

Vincentklw
  • 61
  • 1
  • 6
1

Thanks! It works with lambda as well if you have multiple tables you want to disable.

private void yourTableListeners(){
    yourTableView.widthProperty()
            .addListener((observable, oldValue, newValue) -> yourReusableDisablingMethod(yourTableView));
    anotherTableView.widthProperty()
            .addListener((observable, oldValue, newValue) -> yourReusableDisablingMethod(anotherTableView));
}

@SuppressWarnings("restriction")
private void yourReusableDisablingMethod(TableView tableView) {
    TableHeaderRow header = (TableHeaderRow) tableView.lookup("TableHeaderRow");
    header.reorderingProperty().addListener(new ChangeListener<Boolean>() {
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            header.setReordering(false);
        }
    });
}
iamkenos
  • 1,446
  • 8
  • 24
  • 49
1

For FXML user it can easily done by adding reorderable="false"

<TableColumn fx:id="test" text="ColumnTitle" reorderable="false"/>
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
Sparcsky
  • 377
  • 3
  • 15
0

If you down want sorting on the tableview columns and tab reordering there is a simple solution

private void disableHeaderReorderingAndSorting() {
    tableView.skinProperty().addListener((a, b, newSkin) ->
    {
        Pane header = (Pane) tableView.lookup("TableHeaderRow");
        header.setMouseTransparent(true);
    });
}
citizen
  • 53
  • 1
  • 6