0

Before I start: I'm a newbee in JavaFX and with this project i want to learn how to use this library properly.

The situation is the following: i have a server-client application. The server sends the client a list of the active users on the server. Now i want to list the active users in the UI. I wanted to do that with buttons in FlowPane. The problem is that my client is in an external thread, so not in the application-thread. But because of the fact that the client gets the list on users, I tried to update the button-list directly from the client-thread.

            if(data.getObject() instanceof ArrayList<?>) {
                ArrayList<User> activeUsers = (ArrayList<User>) data.getObject();
                controller.setActiveUsers(activeUsers);
            }

The method in my controller does the following:

public void setActiveUsers(ArrayList<User> activeUsers) {
    for(User user:activeUsers) {
        fpOnlineUsers.getChildren().add(new Button(user.getName()));
    }
}

The Exception i get is the following:java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3

I have two questions:

  1. How can i fix this?
  2. Why blocks JavaFX changed made from threads other than the application-thread?

Please apologize any language mistakes, I'm not a native speaker :)

Peter
  • 15
  • 2
  • You can fix this by using [Platform#runLater](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html#runLater-java.lang.Runnable-) to update your `FlowPane`. You have to do this in the JavaFX aplication thread because [it is not thread safe](https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm) like Swing. – Pagbo Jul 10 '18 at 15:19
  • @Pagbo Swing is [not thread safe](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) either (some parts are, as stated in the link, but they are specially documented as such). – Slaw Jul 10 '18 at 15:22
  • @Slaw that 's what I said, or at least I wanted to say (I personnally consider Swing is not thread safe at all). – Pagbo Jul 10 '18 at 15:25
  • 1
    @Pagbo Oops, sorry. When I read "_like Swing_" I interpreted it as "_in contrast to Swing_" and not as "_similar to Swing_". – Slaw Jul 10 '18 at 15:26
  • 1
    @Slaw I noticed after your first comment it was a little confusing. Sorry for the misunderstanding and thanks to enlighten it. – Pagbo Jul 10 '18 at 15:30

1 Answers1

0
  1. You need to make any JavaFX object related calls on the Application Thread. To do this from your client Thread use the Application.runlater(Runnable) function.

Your code should look something like this:

public void setActiveUsers(ArrayList<User> activeUsers) {
    Platform.runLater(new Runnable() {
        @Override public void run() {
            for(User user:activeUsers) {
                fpOnlineUsers.getChildren().add(new Button(user.getName()));
            }
        }
    }
});

Reference: Platform.runLater and Task in JavaFX

Jan Soe
  • 51
  • 4