2017-04-06 93 views
2

我從我的服務器接收字符串,我想要在客戶端(Think聊天窗口)附加到Textarea。問題是,當我收到字符串時,客戶端凍結。將文本附加到TextArea(JavaFX 8)

insertUserNameButton.setOnAction((event) -> { 
     userName=userNameField.getText(); 
     try { 
      connect(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }); 

public Client() { 
    userInput.setOnAction((event) -> { 

     out.println(userInput.getText()); 
     userInput.setText(""); 

    }); 
} 

private void connect() throws IOException { 

    String serverAddress = hostName; 
    Socket socket = new Socket(serverAddress, portNumber); 
    in = new BufferedReader(new InputStreamReader(
      socket.getInputStream())); 
    out = new PrintWriter(socket.getOutputStream(), true); 

    while (true) { 
      String line = in.readLine(); 

     if (line.startsWith("SUBMITNAME")) { 
      out.println(userName); 

     } else if (line.startsWith("MESSAGE")) { 
      Platform.runLater(()->serverOutput.appendText(line.substring(8) + "\n")); 

     } else if (line.startsWith("QUESTION")) { 
      Platform.runLater(()->serverOutput.appendText(line.substring(8) + "\n")); 

     } else if (line.startsWith("CORRECTANSWER")) { 
      Platform.runLater(()->serverOutput.appendText(line.substring(14) + "\n")); 
     } 
    } 
} 

public static void main(String[] args) { 
    launch(args); 
} 

我已經做了一些研究,似乎在每個append上使用Platform.runLater應該可以解決問題。它不適合我。

任何人都知道它可能造成什麼?謝謝!

+0

你在哪裏調用'連接()'?在什麼線程上? –

+0

我編輯了代碼。它從行動事件中調用。啓動連接的連接按鈕。沒有線程。 – binerkin

+0

如果您是從事件處理程序調用它,那麼它將在FX應用程序線程中運行。所以你的無限'while(true){...}'循環在FX應用程序線程上運行,阻塞它並阻止UI執行任何更新。你需要在後臺線程上運行它。 –

回答

2

您在FX應用程序線程上致電connect()。因爲它會阻止無限期地通過

while(true) { 
    String line = in.readLine(); 
    // ... 
} 

結構,你擋住了FX應用程序線程,並防止它做任何其日常工作的(渲染用戶界面,響應用戶事件等)。

你需要在後臺線程上運行它。這是最好用Executor管理線程:

private final Executor exec = Executors.newCachedThreadPool(runnable -> { 
    Thread t = new Thread(runnable); 
    t.setDaemon(true); 
    return t ; 
}); 

然後做

insertUserNameButton.setOnAction((event) -> { 
    userName=userNameField.getText(); 
    exec.execute(() -> { 
     try { 
      connect(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }); 
}); 
+0

這樣做!謝謝! – binerkin