简体   繁体   中英

JavaFx and socket listener

we are developing a client-server application which has to work both with GUI and CLI. We have no problem with the CLI but we are struggling to implment it with JavaFX:

our server send some objects to the client (via socket) and these have to be processed.

This is our SocketServerListener (and writer):

public class SockeServerListener extends Thread implements ServerListener{
    private CliController controller;
    private ObjectInputStream in;
    private ObjectOutputStream out;

    public SocketServerListener(Socket server, CliController controller) throws UnknownHostException, IOException {
        this.controller = controller;
        this.out = new ObjectOutputStream(server.getOutputStream());
        this.in = new ObjectInputStream(server.getInputStream());
    }

    public void publishMessage(String message) throws IOException, RemoteException {
        out.writeObject(message);
        out.flush();
    }

    public void run() {
        try {
            while (true) {
                Dialogue dialogue = (Dialogue) in.readObject();
                controller.parseDialogue(dialogue);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


}

The SocketServerListener is instantiated by the controller which is the one who executes the who "executes" the received object, updating the interface (Cli/GUI)

public void parseDialogue(Dialogue dialog) {
        dialog.execute(view); //view is an interface extended by both the Cli and GUI
        this.canWrite = true;
    }

As I said, this works very well with the CLI, but it throws an exception with JavaFX

Exception in thread "Thread-7" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-7

We tried to use the Class used to generate all the GUI as controller, but without any (positive) result. How can we instantiate a thread so that it can work with JavaFX and call the methods that show the screens we need?

Thank you

Not on FX application thread

gives you the cause of the issue.

According to the Javadoc of the Node class:

Node objects may be constructed and modified on any thread as long they are not yet attached to a Scene in a Window that is showing. An application must attach nodes to such a Scene or modify them on the JavaFX Application Thread.

Use Platform.runLater to execute code on the FX application thread and also have a look at the javafx.concurrent package for further utility classes.

Presumably the call to controller.parseDialogue(dialogue); is updating the UI. You can only do this on the FX Application Thread. You can schedule a runnable to execute on the FX Application Thread using Platform.runLater() :

Platform.runLater( () ->  controller.parseDialogue(dialogue) );

Note that if you don't know you are executing this code in a context in which the FX toolkit has been started, the call to Platform.runLater(...) should be made in the controller instead, eg

public class NonGuiController implements CliController {

    @Override
    public void parseDialog(Dialogue dialogue) {
        // regular code here... 
    }
}

and

public class GuiController implements CliController {

    @Override
    public void parseDialogue(Dialogue dialogue) {
        // some preliminary work (still on background thread here) if necessary...
        Platform.runLater(() -> {
            // code that updates UI here...
        });
    }
}

and revert to the original code in your socket listener class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM