Reputation: 1400
I am creating a JavaFX
application, I need the GUI to interact with some other code in the class but the GUI and the other piece of code obviously can't run without me making different Thread
s for them to run on.
public class Client extends Application {
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage){
primaryStage.setTitle("Hello world!");
Button btn = new Button();
btn.setText("Run Client");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
try{runClient();}catch (Exception e){System.out.println("Exception Occurred, Server is down.");}
}
});
StackPane root = new StackPane();
root.getChildren().addAll(btn);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
public void runClient() throws Exception {
String sentence;
String modSentence;
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
modSentence = inFromServer.readLine();
System.out.println("From Server: " + modSentence);
clientSocket.close();
}
runClient()
is the client for the server. I need the GUI to communicate with the client but I can't make a new Thread
to run both of them simultaneously.
Upvotes: 4
Views: 5436
Reputation: 1798
Here is what I think you want. You create an ExecutorService which handles multithreading for you. Then you submit Tasks to it with execute(). You can read the basics in the link.
When you want to do some UI stuff from outside the FXThread you just call:
Platform.runLater(some Runnable with GUI code);
And it runs on the FXThread.
public class Client extends Application {
//Create a ExecutorService threadpool
ExecutorService threadPool = Executors.newWorkStealingPool();
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage){
primaryStage.setTitle("Hello world!");
Button btn = new Button();
btn.setText("Run Client");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
try {
//submit a new task to the threadPool which will be executed on another thread.
threadPool.execute(new Runnable() {
@Override
public void run() {
runClient();
}
});
} catch (Exception e) {
System.out.println("Exception Occurred, Server is down.");
}
}
});
StackPane root = new StackPane();
root.getChildren().addAll(btn);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
public void runClient() throws Exception {
String sentence;
String modSentence;
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + "\n");
modSentence = inFromServer.readLine();
System.out.println("From Server: " + modSentence);
clientSocket.close();
//############# Run something in the FXThread #############\\
Platform.runLater(new Runnable() {
@Override
public void run() {
//do some UI stuff like updating labels
}
});
}
}
Edit:
Which ExecutorService you should use depends on the type of application you write. WorkStealing might not be the best for you, but I don't know how your application looks overall so I took it as an example. You can read more about the different Thread Pools here.
Edit 2:
Also if you use JavaFX-8 you can use Lambdas, which make you code much shorter.
You can write:
Platform.runLater(() -> {
//DO STUFF HERE
});
or
threadPool.execute(() -> {
runClient();
});
or
btn.setOnAction(event -> {
try {
...
} catch(Exception e) {
...
}
});
Upvotes: 3