BufferedReader冻结了Javafx中的UI

时间:2016-04-28 06:01:54

标签: javafx

我正在研究Javafx。我创建了一个echo ServerClient系统,即将数据发送到服务器并返回给所有客户端(广播)。当客户端向服务器发送数据时,它工作正常。但是当服务器将数据发送回客户端时,框架会冻结。这是代码: 客户端:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rajeshpatkar;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @author Dimpi
 */
public class Client  extends Application{

    int flag = 999;


    public void start(Stage primaryStage) throws Exception {

        Connect cnn = new Connect(primaryStage);
        cnn.sconnect();

    }

    public static TextArea Frame(Stage primaryStage, PrintWriter nos, BufferedReader nis) throws IOException {

        TextField tf = new TextField();
        TextArea ta = new TextArea();
        Button btn = new Button();
        btn.setText("Click");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

                String get = tf.getText();
                nos.println(get);
                try {
                    Connect.chat(nis,ta);
                } catch (IOException ex) {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        });

        BorderPane root = new BorderPane();
        root.setCenter(ta);
        BorderPane panel = new BorderPane();
        root.setBottom(panel);
        panel.setCenter(tf);
        panel.setRight(btn);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
        return ta;

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

class Connect {

    Stage primaryStage;

    Connect(Stage primaryStage) {
        this.primaryStage = primaryStage;
    }

    public void sconnect() throws IOException {
        System.out.println("Client Signing IN");
        Socket soc = new Socket("localhost", 9081);
        PrintWriter nos = new PrintWriter(
                new BufferedWriter(
                        new OutputStreamWriter(soc.getOutputStream()
                        )
                ), true);
        BufferedReader nis = new BufferedReader(
                new InputStreamReader(soc.getInputStream()
                )
        );

        TextArea ta=Client.Frame(primaryStage, nos, nis);

    }

    public static void chat(BufferedReader nis,TextArea ta) throws IOException{

        String set = nis.readLine();

        while (!set.equals("End")) {
            ta.appendText(set+"\n");
            set = nis.readLine();

        }
    }
}


Server: /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rajeshpatkar;

import static com.rajeshpatkar.Server.a1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @author Dimpi
 */
public class Server extends Application {
    public static ArrayList<PrintWriter> a1=new ArrayList<PrintWriter>();

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

        System.out.println("Server signing IN");
        ServerSocket ss = new ServerSocket(9081);
        for (int i = 0; i < 5; i++) {
            Socket soc = ss.accept();
            Conversation c = new Conversation(soc);
            c.start();
        }

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

class Conversation extends Thread {

    Socket soc;

    Conversation(Socket soc) {
        this.soc = soc;
    }

    public void run() {
        try {

            PrintWriter nos = new PrintWriter(
                    new BufferedWriter(
                            new OutputStreamWriter(soc.getOutputStream()
                            )
                    ), true);
            BufferedReader nis = new BufferedReader(
                    new InputStreamReader(soc.getInputStream()
                    )
            );
            Server.a1.add(nos);
            String get=nis.readLine();
            while(true){
              for(PrintWriter p:a1){
            System.out.println(get);

            p.println(get);
              }
            get=nis.readLine();
            }

        } catch (Exception e) {

        }

    }
}

1 个答案:

答案 0 :(得分:0)

冻结客户端ui的问题导致您的方法:chat()。这是你的按钮调用的。它包含readLine()的{​​{1}}方法,它将等待输入发生。此等待将导致冻结,因为它发生在应用程序线程上。

所以你可以做的是:在你的button-eventhandler上: only 写输出:

BufferedReader

但添加一个Thread,如果您的InputStream接收到输入,将更新TextArea,例如像这样:

String get = tf.getText();
nos.println(get);

并调用该方法一次:

static void handleInput(BufferedReader nis, TextArea ta) throws IOException {

    final Task<Void> task = new Task<Void>() {
        @Override
        protected Void call() throws Exception {
            String output;
            while ((output = nis.readLine()) != null) {
                final String value = output;
                Platform.runLater(new Runnable() {

                    @Override
                    public void run() {
                        ta.appendText(value + System.getProperty("line.separator"));
                    }
                });
            }
            return null;
        }
    };
    new Thread(task).start();
}