【问题标题】:Issues appending text to a TextArea (JavaFX 8)将文本附加到 TextArea (JavaFX 8) 的问题
【发布时间】:2017-04-06 14:49:43
【问题描述】:

我正在从我的服务器接收字符串,我想将这些字符串附加到客户端的文本区域(思考聊天窗口)。问题是,当我收到字符串时,客户端冻结了。

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

我做了一些研究,似乎在每个追加上使用 Platform.runLater 应该可以解决问题。它不适合我。

有人知道它可能是由什么引起的吗?谢谢!

【问题讨论】:

  • 你在哪里打电话connect()?在什么线程上?
  • 我已经编辑了代码。它是从动作事件中调用的。启动连接的连接按钮。没有线程。
  • 如果您从事件处理程序调用它,那么它在 FX 应用程序线程中运行。因此,您的无限 while (true) { ... } 循环在 FX 应用程序线程上运行,阻止它并阻止 UI 执行任何更新。您需要在后台线程上运行它。
  • 有道理!我会尝试一下。非常感谢!

标签: javafx server append client textarea


【解决方案1】:

您正在 FX 应用程序线程上调用 connect()。因为它通过

无限期阻塞
while(true) {
    String line = in.readLine();
    // ...
}

构造,您阻止 FX 应用程序线程并阻止它执行任何常规工作(呈现 UI、响应用户事件等)。

您需要在后台线程上运行它。最好使用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();
        }
    });
});

【讨论】:

  • 做到了!谢谢!
猜你喜欢
  • 2016-08-28
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
相关资源
最近更新 更多