java - 在 JavaFX setOnAction() 方法中写入 OutputStream

标签 java javafx

我正在编写一个JavaFX应用程序(它应该是一个简单的聊天应用程序)。现在,我尝试在每次按下按钮时在 OutputStream 上写入。事实是它不起作用,看起来信息已写入,但我无法从 InputStream 中读取它。

我有两个类:其中之一是接口(interface)(extends Application)。它有一个 TextField 和一个“发送”按钮。当我在文本字段中写入内容并按下此按钮时,TextField 中的文本将写入 OutputStream。另一方面,另一个类(Thread)正在从InputStream 中读取。即使信息已写入流,readLine() 方法也不起作用,它一直等待接收数据。

我有什么遗漏的吗?提前致谢。

JavaFX 应用程序

import java.io.*;
import java.net.Socket;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class ChatApp extends Application {

    int indexMsg = 0;

    Socket socket;
    BufferedReader br;
    PrintWriter pw;

    public ChatApp() throws IOException {

        this.socket = new Socket("localhost", 56700);
        this.pw = new PrintWriter(socket.getOutputStream());
        this.br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    }

    @Override
    public void start(Stage primaryStage) throws IOException {

        GridPane root = new GridPane();
        root.setAlignment(Pos.CENTER);
        root.setVgap(10);
        root.setPadding(new Insets(10,10,10,10));

        ScrollPane msgPane = new ScrollPane();
        msgPane.setPrefSize(280, 280);
        msgPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);

        GridPane msgPaneContent = new GridPane();
        msgPaneContent.setPrefWidth(270);
        msgPaneContent.setVgap(10);

        FlowPane writePane = new FlowPane(10,10);
        writePane.setAlignment(Pos.CENTER);
        writePane.setPrefWidth(280);

        TextField writeMsg = new TextField();
        writeMsg.setPrefWidth(200);
        writeMsg.setPromptText("Write your message");

        Button send = new Button("Send");


        send.setOnAction((ev) -> {
            TextArea msg = new TextArea(writeMsg.getText());
            msg.setMaxWidth(135);
            msg.setPrefRowCount(msg.getLength()/21 + 1);
            msg.setWrapText(true);

            GridPane.setConstraints(msg, 0, indexMsg++); 

            writeMsg.deleteText(0, writeMsg.getText().length());
            msgPaneContent.getChildren().add(msg);

            String message = msg.getText();

            pw.write(message);
            System.out.println("Sent " + msg.getText());

        });

        writePane.getChildren().addAll(writeMsg, send);

        GridPane.setConstraints(msgPane, 0, 0);
        GridPane.setConstraints(writePane, 0, 1);

        msgPane.setContent(msgPaneContent);
        root.getChildren().addAll(msgPane, writePane);

        Scene scene = new Scene(root, 300, 300);

        primaryStage.setTitle("Chat App");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {

        launch(args);

    }

}

接收者线程

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ChatServer extends Thread {

    ServerSocket server;
    Socket socket;
    BufferedReader br;
    PrintWriter pw;

    public ChatServer() throws IOException {
        server = new ServerSocket(56700);
        socket = server.accept();
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        pw = new PrintWriter(socket.getOutputStream());

    }

    public void run() {
        String msg = null;

        while (true) {

            try {
                msg = br.readLine();
            } catch (IOException ex) {
                System.out.println("Error");
            }

            System.out.println(msg);
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        (new ChatServer()).start();
    }

}

最佳答案

您的消息不包含行结束符。服务器中的 readLine() 方法读取流中的所有内容,查找行尾标记,然后连接所有字符以形成文本行。因此,您需要从客户端发送一个行结束符。

您还应该在发送消息后刷新打印写入器 - 否则打印写入可能会在实际发送消息之前缓冲许多消息:

send.setOnAction((ev) -> {
    TextArea msg = new TextArea(writeMsg.getText());
    msg.setMaxWidth(135);
    msg.setPrefRowCount(msg.getLength()/21 + 1);
    msg.setWrapText(true);

    GridPane.setConstraints(msg, 0, indexMsg++); 

    writeMsg.deleteText(0, writeMsg.getText().length());
    msgPaneContent.getChildren().add(msg);

    String message = msg.getText();

    pw.write(message + "\n");
    pw.flush();

    System.out.println("Sent " + msg.getText());

});

关于java - 在 JavaFX setOnAction() 方法中写入 OutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45862573/

相关文章:

Java 的 WeakHashMap 和缓存 : Why is it referencing the keys, 不是值?

java - JXTable背景图像不渲染

javascript - JAVA FX + Javascript

JavaFX 相当于 ProgressMonitor

java - Jersey:ContainerRequestFilter 抛出错误

java - 矩形网格内的三角形

JavaFX - 防止在缩放的 Canvas 上模糊以进行像素化缩放

JavaFX TableView 和 ObservableList - 如何自动更新表?

java - 如何在java中使用正则表达式允许空字符串?

multithreading - 重新实现 JavaFX showAndWait