JavaFX, conexión por socket

Iniciado por Zoik, 25 Junio 2015, 13:05 PM

0 Miembros y 1 Visitante están viendo este tema.

Zoik

Buenas a todos gente.

Tengo una preguntilla respecto a este tema, como podria hacer para tener una gui y que a la hora de conectar con el servidor no se me congelase la interface, pongo el código hasdta ahora:

Código (java) [Seleccionar]

package app;

import java.io.IOException;

import app.view.NewServerController;
import app.view.RootController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;


public class Main extends Application
{

private Stage stage;
private BorderPane rootLayout;

public static void main(String[] args)
{
launch(args);
}

@Override
public void start(Stage stage) throws Exception
{
this.stage = stage;
this.stage.setTitle("Fenrir");

initRootLayout();
}

public void initRootLayout()
{
try
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/Root.fxml"));
rootLayout = (BorderPane) loader.load();

RootController controller = loader.getController();
controller.setMain(this);

Scene scene = new Scene(rootLayout);
stage.setScene(scene);
stage.show();
} catch(IOException e)
{
e.printStackTrace();
}
}

public boolean showNewServerDialog()
{
try
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/NewServer.fxml"));
BorderPane page = (BorderPane) loader.load();

Stage stage = new Stage();
stage.setTitle("Conectar a servidor");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(this.stage);
Scene scene = new Scene(page);
stage.setResizable(false);
stage.setScene(scene);

NewServerController controller = loader.getController();
controller.setDialogStage(stage);

stage.showAndWait();

return controller.isOkCliked();
} catch(IOException e)
{
e.printStackTrace();
return false;
}
}

}


Código (java) [Seleccionar]

package app.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client
{

private String hostname;
private int puerto;
Socket socket;
DataOutputStream mensaje;
DataInputStream entrada;

public Client(String hostname, int puerto)
{
this.hostname = hostname;
this.puerto = puerto;
}

public boolean InitClient()
{
try
{
socket = new Socket(hostname, puerto);
entrada = new DataInputStream(socket.getInputStream());
mensaje = new DataOutputStream(socket.getOutputStream());
System.out.println(entrada.readUTF());
mensaje.writeUTF("Hola que tal!");
System.out.println(entrada.readUTF());
socket.close();
} catch(UnknownHostException e)
{
e.printStackTrace();
return false;
} catch(Exception e)
{
e.printStackTrace();
return false;
}
return true;
}

}


Código (java) [Seleccionar]

package app.view;

import org.controlsfx.dialog.Dialogs;

import app.client.Client;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class NewServerController
{
@FXML
private TextField hostnameIpTextField;
@FXML
private TextField puertoTextField;
@FXML
private TextField userTextField;
@FXML
private TextField passwordTextField;
@FXML
private TextField nameTextField;

private Stage stage;
private boolean okClicked = false;

public void setDialogStage(Stage stage)
{
this.stage = stage;
}

public boolean isOkCliked()
{
return okClicked;
}

private boolean isInputValid()
{
String errorMessage = "";

if(hostnameIpTextField.getText() == null
|| hostnameIpTextField.getText().length() == 0)
errorMessage += "Hostname/Ip no válido!\n";
if(puertoTextField.getText() == null
|| puertoTextField.getText().length() == 0
|| Integer.parseInt(puertoTextField.getText()) < 0
|| Integer.parseInt(puertoTextField.getText()) > 65535)
errorMessage += "Puerto no válido!\n";
if(errorMessage.length() == 0)
{
return true;
} else
{
Dialogs.create()
           .title("Campos inválidos")
           .masthead("Por favor, corrige los campos no válidos")
           .message(errorMessage)
           .showError();
       return false;
}
}

@FXML
private void handleConectar() throws InterruptedException
{
if(isInputValid())
{
Client client = new Client(hostnameIpTextField.getText(), Integer.parseInt(puertoTextField.getText()));
boolean connected = client.InitClient();
if(connected)
{
okClicked = true;
stage.close();
}
}
}

@FXML
private void handleCancelar()
{
stage.close();
}

}


Código (java) [Seleccionar]

package app.view;

import javafx.fxml.FXML;
import app.Main;

public class RootController
{

private Main main;

public void setMain(Main main)
{
this.main = main;
}

@FXML
private void handleNewServer()
{
boolean okClicked = main.showNewServerDialog();
}

}


Imagino que se hará la ejecución de la conexión del socket en un thread a parte, pero no me acaba de quedar claro como haría la trata de errores en el thread.

La idea que tenia era que en cuanto le de a conectar, me abra el socket en un thread separado para que la interface no se congele y en cuanto se conecte correctamente  (o no) avise al thread principal para que actue en consecuencia.

Un saludo y gracias de antemano.

Zoik

#1
Bueno, me respondo en otro post, no se si será el método mas correcto pero aquí lo dejo por si a alguien le interesa.

Código (java) [Seleccionar]

package app.view;

import org.controlsfx.dialog.Dialogs;

import app.client.Client;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class NewServerController
{
@FXML
private TextField hostnameIpTextField;
@FXML
private TextField puertoTextField;
@FXML
private TextField userTextField;
@FXML
private TextField passwordTextField;
@FXML
private TextField nameTextField;

private Stage stage;
private boolean okClicked = false;

public void setDialogStage(Stage stage)
{
this.stage = stage;
}

public boolean isOkCliked()
{
return okClicked;
}

private boolean isInputValid()
{
String errorMessage = "";

if(hostnameIpTextField.getText() == null
|| hostnameIpTextField.getText().length() == 0)
errorMessage += "Hostname/Ip no válido!\n";
if(puertoTextField.getText() == null
|| puertoTextField.getText().length() == 0
|| Integer.parseInt(puertoTextField.getText()) < 0
|| Integer.parseInt(puertoTextField.getText()) > 65535)
errorMessage += "Puerto no válido!\n";
if(errorMessage.length() == 0)
{
return true;
} else
{
Dialogs.create()
           .title("Campos inválidos")
           .masthead("Por favor, corrige los campos no válidos")
           .message(errorMessage)
           .showError();
       return false;
}
}

@FXML
private void handleConectar() throws InterruptedException
{
if(isInputValid())
{
Client client = new Client(hostnameIpTextField.getText(), Integer.parseInt(puertoTextField.getText()));
client.start();
client.join();
boolean ok = client.getOk();
if(ok)
{
System.out.println("Conexion exitosa, cierro modal...");
okClicked = true;
stage.close();
}  else
{
System.out.println("Conexion fallida...");
}

}
}

@FXML
private void handleCancelar()
{
stage.close();
}

}


Código (java) [Seleccionar]
package app.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client extends Thread
{

private String hostname;
private int puerto;
private Socket socket;
private DataOutputStream mensaje;
private DataInputStream entrada;
private boolean ok = false;

public Client(String hostname, int puerto)
{
this.hostname = hostname;
this.puerto = puerto;
}

public boolean getOk()
{
return ok;
}

public boolean InitClient()
{
try
{
socket = new Socket(hostname, puerto);
entrada = new DataInputStream(socket.getInputStream());
mensaje = new DataOutputStream(socket.getOutputStream());
System.out.println(entrada.readUTF());
mensaje.writeUTF("Hola que tal!");
System.out.println(entrada.readUTF());
socket.close();
} catch(UnknownHostException e)
{
e.printStackTrace();
return false;
} catch(Exception e)
{
e.printStackTrace();
return false;
}
return true;
}

public synchronized void run()
{
System.out.println("Inicio Thread");
ok = InitClient();
System.out.println("Conexion finalizada, notifico a thread principal");
notifyAll();
System.out.println("Notificado a thread");
}

}


Me sigue congelando la screen, pero al menos me espera a tener la respuesta afirmativa del thread del socket.

Un saludo y agradecería me comentarais si hay alguna forma mejor.