La mise à jour de la JavaFx Gui avec des fils et des Tâches ou des

Je suis entrain de créer un programme de chat qui contient une interface graphique que j'ai crée dans la nouvelle version de JavaFx Scene builder. J'ai une méthode main qui étend le champ d'application et j'ai un simpleController (qui contrôle tous les boutons, les étiquettes, les anchorPanes, etc) dans mon interface graphique.

Autre que cela, j'ai une application serveur qui permet de recevoir et envoyer des messages. Pour cela, j'ai créé le protocole simple suivant:

Commandes /Description:

  • 1 - Demander l'autorisation de se connecter et dans le même temps, demander à un utilisateur
    ID (serveur sait combien d'utilisateurs sont en ligne, et ajoute l'id+1)
  • 2 - Chat, le client envoie un IDENTIFIANT et d'un String message (Exemple: 21

    Bonjour (note tous ces éléments sont sur une ligne distincte))
  • 3 - Déconnecte le client.
  • 4 - Affiche une liste de tous les clients en ligne.
  • 5 - Demander qui d'autre est en ligne (ce n'est que lorsqu'un utilisateur est
    la connexion et il a besoin de savoir combien d'utilisateurs sont en ligne afin de
    mise à jour de l'interface graphique).
  • 10 - Erreur de toutes sortes si le serveur renvoie le 10 message qu'il signifie
    que l'appel au client a juste fait une erreur ou qu'il ne pouvait pas

    être achevé!

À l'aide de cette simple logique, il devrait être assez facile pour moi de faire aux utilisateurs de se connecter, le chat et la débrancher. Cependant, il s'est avéré que ce qui aurait dû être une simple tâche s'est avéré être mon pire cauchemar.

Pour l'instant, mes utilisateurs n'a pas de problème de connexion pour le programme et plus d'utilisateurs peuvent se connecter en même temps.

Où les choses commencent à devenir délicat, c'est quand je veux envoyer et recevoir des messages entre le serveur et le client.

Je ne sais pas comment je peux mettre à jour mon GUI, tout en utilisant un fil. J'ai essayé de lire sur la Tâche de la classe, mais je suis incapable de voir de savoir si cela devrait être utilisé au lieu d'un fil ou le fil doit avoir cela comme un paramètre.

Dois-je créer une nouvelle classe qui écoute d'entrée et de rendre cette classe étendre fil? OU

Le thread doit être en cours d'exécution dans ma simpleController classe?

Principal

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

Client

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

Je suis vraiment désolé pour le code nature du désordre. La méthode run() du contrôleur simple était une tentative de faire un thread de la simpleController. Toutefois, cela n'a pas fonctionné comme je l'espérais. 🙁

L'objectif principal de ce est essentiellement pour s'assurer que les deux personnes dans la salle de chat peuvent discuter ensemble. Donc, tout ce qu'il a à faire est de mettre à jour 1 ou 2 textareas.