2

新しいバージョンのJavaFxSceneBuilderで作成したGUIを含むチャットプログラムを作成しています。アプリケーションを拡張するメインメソッドがあり、GUIにsimpleController(すべてのボタン、ラベル、anchorPanesなどを制御する)があります。

それ以外に、メッセージを送受信できるサーバーアプリケーションがあります。この目的のために、私は次の簡単なプロトコルを作成しました。

コマンド/説明:

  • 1-接続の許可を求めると同時に、ユーザーIDを要求します(サーバーはオンラインのユーザー数を確認し、id + 1を追加します)
  • 2-チャット、クライアントはIDと文字列メッセージを送信します(例:21
    こんにちは(これらはすべて別の行にあることに注意してください))
  • 3-クライアントを切断します。
  • 4-オンラインのすべてのクライアントのリストを表示します。
  • 5-他に誰がオンラインであるかを尋ねます(これは、ユーザーが接続しているときにのみ使用され、GUIを更新するためにオンラインになっているユーザーの数を知る必要があります)。

  • 10-サーバーが10メッセージを返した場合、あらゆる種類のエラーが発生します。これは、クライアントが行ったばかりの呼び出しがエラーであったか、完了 できなかったことを意味します。

この単純なロジックを使用すると、ユーザーが接続、チャット、および切断できるようにするのはかなり簡単なはずです。しかし、単純な作業であるはずだったことが、私の最悪の悪夢であることが判明しました。

これまでのところ、私のユーザーはプログラムに接続するのに問題はなく、より多くのユーザーが同時に接続できます。

物事がトリッキーになり始めるのは、サーバーとクライアントの間でメッセージを送受信したいときです。

スレッドの使用中にGUIを更新する方法がわかりません。Taskクラスを読み上げようとしましたが、これをスレッドの代わりに使用する必要があるのか​​、スレッドでこれをパラメーターとして使用する必要があるのか​​がわかりません。

入力をリッスンする新しいクラスを作成し、そのクラスにスレッドを拡張させる必要がありますか? または
スレッドをsimpleControllerクラスで実行する必要がありますか?

主要

public class Main extends Application{
    public static void main(String[] args) throws IOException{
        Application.launch(Main.class, (java.lang.String[]) null);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        try {
            AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class.getResource("testingBackground.fxml"));
            Scene scene = new Scene(page);
            primaryStage.setScene(scene);
            primaryStage.setTitle("Chatten");
            primaryStage.show();

        } catch (Exception ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        }
    }
}

simpleController

import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Scanner;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import com.sun.glass.ui.Platform;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Text;

/*
 * evt ret array listen med commands da jeg selv kan styre hvilke commands der kommer ind og ud! og brugeren faktisk
 * aldrig selv kan vælge!
 */
public class SimpleController extends Thread implements Initializable{
    public Button btn_Connect;
    public AnchorPane pictureFrame;
    public Socket socket = new Socket();
    public PrintWriter pw;
    public Scanner input;
    public int clientId = 1;
    public Client client = new Client(socket, pw, input, clientId);
    // options!
    public TextField txt_userName;
    public TextField textField_chat;
    // send button
    public Button Send;
    /*
     * current client that the user i connected with, this client is used to send commands and tell other clients who is connected on
     * what "ingame chat persons"
     */
    public static int currentClientId;
    // chatperson username
    public Label lbl_userName2;
    public Label lbl_userName3;
    public Label lbl_chatPerson2;
    public Label lbl_Chatperson1_userName;
    //Pictures of chat person
    public Label chatPerson3;
    public Label chatPerson1;
    // chat persons textfield
    public TextArea txt_ChatPerson1;
    //public TextField txt_ChatPerson1;
    public TextField txt_ChatPerson2;
    public TextField txt_ChatPerson3;


    @Override
    public void initialize(URL location, ResourceBundle resources) throws NullPointerException {
        try {
            client.connect();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        pictureFrame.setMaxSize(409, 373);
        txt_ChatPerson1.setMinWidth(50);
        txt_ChatPerson1.setPrefWidth(50);
        txt_ChatPerson1.setMaxWidth(300);
        txt_ChatPerson1.setText("         ");



        btn_Connect.setOnAction(new EventHandler<ActionEvent>() {   
            @Override

            public void handle(ActionEvent event) throws NullPointerException {
                connectMeWithOthers(1);
            }
        });

        Send.setOnAction(new EventHandler<ActionEvent>() {

            // WORK IN PROGReSS!!
            @Override
            public void handle(ActionEvent event) {

                /*
                 * new line code:
                 */
                String x = textField_chat.getText();
                txt_ChatPerson1.setText(x);
                txt_ChatPerson1.setVisible(true);
                System.out.println("x" +x);

                txt_ChatPerson1.textProperty().addListener(new ChangeListener<String>() {

                    @Override
                    public void changed(
                            ObservableValue<? extends String> observable,
                            String oldValue, String newValue) {


                        //  txt_ChatPerson1.setPrefRowCount(5);
                        txt_ChatPerson1.setPrefWidth(txt_ChatPerson1.getText().length()*7);
                        //txt_ChatPerson1.setPrefHeight(txt_ChatPerson1.getText().length()*3);
                    }
                });
                txt_ChatPerson1.autosize();
                client.SendChat(x);
            }
        });
    }

    /**
     * this method connect the client to the other clients who are online on the server!
     * the method calls it self after the user has established connection in order to load the other chat persons online
     * if the client is the online user online then it will only load the user
     * @param id
     */
    protected void connectMeWithOthers(int id) {
        try {
            int responseId = client.sendCommando(id);
            System.out.println(" response id "+responseId);
            // finds whom is connected and tries to connect to a spot that is avalibul!
            //Response is the ID of the chat persons
            switch (responseId) {
            case 1:
                currentClientId = client.reciveCommando();
                client.setClientId(currentClientId);
                client.sendString(txt_userName.getText());
                connectMeWithOthers(5);
                break;  
            case 5:
                int times = client.reciveCommando();
                int o = 0;
                System.out.println("times: "+times);

                while (o != times) {
                    int j = client.reciveCommando();
                    System.out.println("j"+ j);
                    String name = client.reciveString();
                    System.out.println("Name " +name);
                    createUser(j, name);    
                    o++;
                }
                start();
                break;

            case 10:
                System.out.println("Connection fail chat room is full! Please try again later!");

            case 8:
                start();
                break;
            default:
                break;
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    private void createUser(int j, String reciveChat) {
        if (j == 1) {
            chatPerson1.setVisible(true);
            lbl_Chatperson1_userName.setVisible(true);
            lbl_Chatperson1_userName.setText(reciveChat);

        }else if (j == 2) {
            lbl_chatPerson2.setVisible(true);
            lbl_userName2.setVisible(true);
            lbl_userName2.setText(reciveChat);
        }else if (j == 3){
            chatPerson3.setVisible(true);
            lbl_userName3.setVisible(true);
            lbl_userName3.setText(reciveChat);
        }else {
            Image img = new Image(getClass().getResourceAsStream("Figur.png"));
            Label test2 = new Label("", new ImageView(img));
            test2.setLayoutX(50);
            test2.setLayoutY(30);
            test2.setPrefSize(1000, 1000);
            pictureFrame.getChildren().addAll(test2);
            test2.setVisible(true);
        }

    }
    /*
     * denne metode er en rewrite af run metoden.
     */
    public void StartClient(){
        ClientListner cl = new ClientListner(client);

        Task task = new Task<String>() {

            @Override
            protected String call() throws Exception {
                // TODO Auto-generated method stub

                return null;
            }
        };
        Thread t = new Thread(task);
        cl.start();
        while (true) {
            if (cl.recived) {

            }
        }
    }

    /*
     * Run metoden er brugt til at recive data fra andre users og update GUI'en skal muligvis rewrites!?
     * 
     */


    public void run(){ 
        System.out.println("Thread started");
        System.out.println(client.getSocket().isConnected());
        ClientListner cl = new ClientListner(client);
        while (client.getSocket().isConnected()) {
            int key = 10;
            if (cl.recived) {

                try {
                    key = client.reciveCommando();
                    System.out.println("jeg er her");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }


            System.out.println("Key "+key);
            switch (key) {
            // case 2 er recive chat:
            case 2:
                // først find ud af hvilket ID der har sendt chatten:
                int y = 0;
                try {
                    y = client.reciveCommando();
                    System.out.println("y" + y); 
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // derefter få beskeden og send den så ud til resten.
                String says = client.reciveChat().toString();
                if (y == 1) {
                    txt_ChatPerson1.setText(client.reciveChat());
                }else if (y == 2) {

                }else {
                    chatPerson3.setVisible(true);
                    txt_ChatPerson3.setVisible(true);
                    txt_ChatPerson3.setText(client.reciveChat());
                }

                break;

            default:
                break;
            }
        }
    }

}

クライアント

import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client {
// disse var static
    public final static int portNumber = 6040;
    public Socket socket;
    private PrintWriter pw;
    private Scanner input;
    private int clientId;
    /**
     * @param args
     * @throws IOException 
     */

    public Client(Socket socket, PrintWriter pw, Scanner input, int clientId){
        this.socket = socket;
        this.pw = pw;
        this.input = input;
        this.clientId = clientId;
    }
    public void connect() throws IOException{
        // du kan vælge at bruge inetadressen til at connecte i socketet.
        InetAddress adr = InetAddress.getByName("localhost");
        socket = new Socket("localhost", portNumber);
        input=new Scanner(socket.getInputStream());
        pw = new PrintWriter(socket.getOutputStream());
    }
    /**
     * This method sends the message (that the client(chat person) writes to the user)
     * @param x
     * @throws NullPointerException
     * @throws IOException 
     */
    public void SendChat(String x) throws NullPointerException{
            pw.println(2);
            pw.flush();
            pw.println(SimpleController.currentClientId);
            pw.flush();
            pw.println(x);
            pw.flush(); 

    }
    public int sendCommando(int id) throws IOException{
        System.out.println("Jeg sender"+ id);
        pw.println(id);
        pw.flush();
        /*
         * this part of the program sends a command to the server if the command is 1 then 1 is = Connect.
         * the program then ask the server is the server is full or is it ok to connect? 
         * if the response is not 10 then the program will allow a connection to happen the return type will be the Id of which 
         * the chat person becomes!
         */
        // should the method return 0 the Application will do NOTHING!
        switch (id) {
        case 1:
    int k = reciveCommando();
            if (k== 10) {
                return 10;
            }else if (k < 3) {
                System.out.println("returned k" + k);
                return k;
            }else {

            return 10;
            }
            /*
             * Closes the connection with the server!
             */
        case 3:

            socket.close();
            return 0;

        case 5:
            int y  = reciveCommando();
            return y;
        default:
            return 0;
        }

    }
    /*
     * this method recives a command from the server! the comands can be found in the ChatCommands.txt
     * returns the command as an integer!
     */
    public int reciveCommando() throws IOException{
        Integer i = input.nextInt();
        return i;
    }
    /**
     * Gets a String response from the server. This method i used to create other users and give them the correct username.
     * 
     * @param i
     * @return
     * @throws IOException
     */
    public String getStringResponse(int i) throws IOException {
        pw.print(i);
        pw.flush();
        String x = input.nextLine();
        return x;

    }
    /*
     * Work in progress - client getter og setter methoder!
     */

    public Socket getSocket(){
        return socket;
    }
    public Scanner getInput(){
        return input;
    }
    public PrintWriter getPw(){
        return pw;
    }
    public int getClientId(){
        return clientId;
    }

    public void setClientId(int i ){
        clientId = i;
    }
    public String reciveChat(){
        String x = getInput().next();
        return x;
    }
    public String reciveString(){
        String x =input.next();
        return x;
    }
    public void sendString(String x){
        pw.println(x);
        pw.flush();
    }

}*

コードが乱雑になって本当に申し訳ありません。simple Controllerのrun()メソッドは、simpleControllerのスレッドを作成する試みでした。しかし、これは私が期待したようには機能しませんでした。:(

これの主な目的は、基本的にチャットルームの2人が一緒にチャットできるようにすることです。したがって、必要なのは1つまたは2つのテキスト領域を更新することだけです。

4

4 に答える 4

5

まだ行っていない場合は、これをチェックしてください

http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

于 2012-10-18T22:13:42.343 に答える
2

これを見つけるのに少し時間がかかったので、ここに文書化しようと思いました。

Platform.runLater(new Runnable(){
@Override
public void run() {
// Update your GUI here.
}
});
于 2013-08-17T17:18:07.383 に答える
1

これは古いですが、グーグルでそこにあったので、私はあなたの最善の策が使用することであることを指摘したいと思います

FXObservableList

また

次のようなBeanプロパティ

DoubleProperty

スレッドセーフです。

于 2013-08-29T04:15:14.983 に答える
0

Java 8を使用している場合:

Platform.runLater(() -> {
            // Update your GUI here.;
        });
于 2016-05-03T22:03:08.167 に答える