2016-06-11 140 views
0

我们正在开发一个客户端 - 服务器应用程序,它必须与GUI和CLI一起工作。 我们对命令行界面没有问题,但是我们很难用JavaFX来实现它: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由控制器是谁执行谁“执行”所接收的对象的一个​​实例,更新界面(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作为控制器的Class,但没有任何(正面)结果。 我们如何实例化一个线程,以便它可以使用JavaFX并调用显示我们需要的屏幕的方法?

谢谢

回答

1

想必调用controller.parseDialogue(dialogue);正在更新UI。您只能在FX应用程序线程上执行此操作。你可以安排一个可运行使用Platform.runLater()的FX应用程序线程来执行:

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... 
     }); 
    } 
} 

并恢复到您的插座监听器类的原代码。

2

没有对外汇的应用程序线程

为您提供了问题的原因。

按照Node类的Javadoc:

Node对象可以被构造和修改在任何线程,只要 他们还没有附着到在被示出窗口场景。一个 应用程序必须将节点附加到这样的场景,或者在JavaFX应用程序线程上修改它们。

使用Platform.runLater到FX应用程序线程上执行代码,也有看看javafx.concurrent包进行进一步的实用程序类。