简体   繁体   English

JavaFx和套接字侦听器

[英]JavaFx and socket listener

we are developing a client-server application which has to work both with GUI and CLI. 我们正在开发一个必须同时使用GUI和CLI的客户端服务器应用程序。 We have no problem with the CLI but we are struggling to implment it with JavaFX: CLI没问题,但是我们努力用JavaFX来实现它:

our server send some objects to the client (via socket) and these have to be processed. 我们的服务器(通过套接字)向客户端发送一些对象,这些对象必须进行处理。

This is our SocketServerListener (and writer): 这是我们的SocketServerListener(和编写器):

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) SocketServerListener由控制器实例化,该控制器是执行“执行”所接收对象,更新接口(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 就像我说的那样,这在CLI上很好用,但是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. 我们尝试使用用于生成所有GUI的Class作为控制器,但是没有任何(肯定的)结果。 How can we instantiate a thread so that it can work with JavaFX and call the methods that show the screens we need? 我们如何实例化一个线程,使其可以与JavaFX一起使用,并调用显示所需屏幕的方法?

Thank you 谢谢

Not on FX application thread 不在FX应用程序线程上

gives you the cause of the issue. 给您问题的原因。

According to the Javadoc of the Node class: 根据Node类的Javadoc:

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. 应用程序必须将节点附加到此类场景,或在JavaFX应用程序线程上对其进行修改。

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. 使用Platform.runLater在FX应用程序线程上执行代码,还可以查看javafx.concurrent包中的更多实用程序类。

Presumably the call to controller.parseDialogue(dialogue); 大概是对controller.parseDialogue(dialogue);的调用controller.parseDialogue(dialogue); is updating the UI. 正在更新用户界面。 You can only do this on the FX Application Thread. 您只能在FX Application Thread上执行此操作。 You can schedule a runnable to execute on the FX Application Thread using Platform.runLater() : 您可以使用Platform.runLater()安排可运行的程序在FX Application线程上执行:

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 请注意,如果您不知道要在已启动FX工具包的上下文中执行此代码,则应改为在控制器中调用Platform.runLater(...) ,例如

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. 并还原为套接字侦听器类中的原始代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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