我们正在开发一个客户端 - 服务器应用程序,它必须同时使用GUI和CLI。 我们对CLI没有任何问题,但我们正在努力用JavaFX来实现它:
我们的服务器将一些对象发送到客户端(通过套接字),这些对象必须进行处理。
这是我们的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();
}
}
}
SocketServerListener由控制器实例化,控制器执行who"执行"收到的对象,更新界面(Cli / GUI)
public void parseDialogue(Dialogue dialog) {
dialog.execute(view); //view is an interface extended by both the Cli and GUI
this.canWrite = true;
}
正如我所说,这对CLI非常有效,但它会抛出JavaFX的异常
Exception in thread "Thread-7" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-7
我们尝试使用用于生成所有GUI作为控制器的类,但没有任何(正面)结果。 我们如何实例化一个线程,以便它可以使用JavaFX并调用显示我们需要的屏幕的方法?
谢谢
答案 0 :(得分:2)
不在FX应用程序线程
告诉您问题的原因。
根据Node类的Javadoc:
可以在任何线程上构建和修改节点对象 它们尚未附加到正在显示的窗口中的场景。一个 应用程序必须将节点附加到此类场景或在其上修改它们 JavaFX应用程序线程。
使用Platform.runLater在FX应用程序线程上执行代码,并查看javafx.concurrent包以获取更多实用程序类。
答案 1 :(得分:1)
大概是对controller.parseDialogue(dialogue);
的调用正在更新UI。您只能在FX应用程序线程上执行此操作。您可以使用Platform.runLater()
Platform.runLater( () -> controller.parseDialogue(dialogue) );
请注意,如果您不知道在FX工具包已启动的上下文中执行此代码,则应在控制器中调用Platform.runLater(...)
,例如。
public class NonGuiController implements CliController {
@Override
public void parseDialog(Dialogue dialogue) {
// regular code here...
}
}
和
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...
});
}
}
并恢复到套接字侦听器类中的原始代码。