5

Odd one here, I can't quite work out how to get around this one. I have a tableview that gets populated when a listener to an observable list picks up there has been a change. So this is the code for that:

userController.getAuthImpl().listOfMessages.addListener(new ListChangeListener<Message>() {
    @Override
    public void onChanged(ListChangeListener.Change<? extends Message> c) {
        addMessageToTableView(tblvwBottomAdminNotifications, c.getList());
    }
});


public void addMessageToTableView(TableView<Message> tblvw, ObservableList<? extends Message> observableList){
    tblvw.getItems().clear();
    for(Message msg: observableList)
        tblvw.getItems().add(msg);
}
public ObservableList<Message> listOfMessages = FXCollections.observableArrayList(_listOfMessages);

This works fine and the table automatically updates once an item is added to the listOfMessages. The bit that I would like to do now, is to scroll the listview to the bottom when it is updated. I've attempted adding the following line to the addMessageToTableView method:

tblvw.scrollTo(tblvw.getItems().size()-1);

And have also attempted adding a change listener to the tableview itself like this:

tblvwBottomAdminNotifications.getItems().addListener(new ListChangeListener<Message>(){

    @Override
    public void onChanged(javafx.collections.ListChangeListener.Change<? extends Message> c) {
        tblvwBottomAdminNotifications.scrollTo(c.getList().size()-1);

    }

});

But both error in the same way with the following message:

Exception in thread "RMI TCP Connection(1)-192.168.56.1" java.lang.IllegalStateException: Not on FX application thread; currentThread = RMI TCP Connection(1)-192.168.56.1

Which from my Google skills is JavaFX complaining I'm accessing the tableview from a separate thread. That I can understand, but how should I access it in such a way that when the tableview does get a new item added to it, it scrolls down to it?

Let me know if you need more information.

Draken
  • 3,134
  • 13
  • 34
  • 54
  • To clarify, tblvw and tblvwBottomAdminNotifications are both TableViews, correct? –  Aug 13 '15 at 15:56
  • 1
    You are changing the UI on a background thread, which is illegal. Read http://stackoverflow.com/questions/30249493/using-threads-to-make-database-requests As an aside, instead of adding the items in a loop as you do (which fires events for every single item added), use `tablevw.getItems().addAll(observableList);` (which fires a single event). – James_D Aug 13 '15 at 17:16
  • You are correct, they are both tableviews. One is in the controller for the GUI and deals with the actual tableview. The other is a generic method in an abstract class that deals with generic table views from other classes. I'm aware I am calling it on the wrong thread, the bottom of my post says so, but how do I call it on the main thread when the tableview auto updates? I'll update the code with the add all to remove the for loop – Draken Aug 14 '15 at 09:51

2 Answers2

10

How about

Platform.runLater( () -> tblvw.scrollTo(c.getList().size()-1) );
1

You could possibly add a changelistener to the Items list of the tableview itself, so that when it is updated, it passively scrolls itself?

tblvw.getItems().addListener(new ListChangeListener<Message>(){

        @Override
        public void onChanged(javafx.collections.ListChangeListener.Change<? extends Message> c) {
            tblvw.scrollTo(c.getList().size()-1);

        }

    });

So instead of adding this listener to the tblvwBottomAdminNotifications, you add it directly to the tblvw. When that tableview is updated, it will call the onChanged method in it's listeners and scroll to the bottom of the list.

  • I should have clarified, the tblvwBottomAdminNotifications is the tableview. That also results in the error as I've already tried it above – Draken Aug 14 '15 at 09:48