Reputation: 35
I want to launch some python scripts from a javafx app. To launch the scripts I use this code :
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
System.out.println(command);
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
public void launchCommand(String inputDir, String outputDir) {
String command = ".\\venv\\Scripts\\python.exe ./test.py -i " + inputDir + " -o " + outputDir;
String output = this.executeCommand(command);
System.out.println(output);
}
The problem is the script is launch by the javafx graphical thread so the line
p.waitFor();
will lock the javafx thread and so my gui stops responding...
I dont know how solve this problem... Thank you in advance for your help !
Upvotes: 1
Views: 1492
Reputation: 209418
Just run the script in a background thread, and make sure you update the GUI back on the FX Application Thread, either using Platform.runLater(...)
or by encapsulating the command as a Task
and using the setOnSucceeded
handler. The best practice here is to use an ExecutorService
to manage the threads.
For example:
private final ExecutorService exec = Executors.newCachedThreadPool();
public void launchCommand(String inputDir, String outputDir) {
String command = ".\\venv\\Scripts\\python.exe ./test.py -i " + inputDir + " -o " + outputDir;
Task<String> commandTask = new Task<String>() {
@Override
protected String call() {
return executeCommand(command);
}
};
commandTask.setOnSucceeded(event -> {
// this is executed on the FX Application Thread,
// so it is safe to update the UI here if you need
System.out.println(commandTask.getValue());
});
commandTask.setOnFailed(event -> {
commandTask.getException().printStackTrace();
});
exec.execute(commandTask);
}
Upvotes: 2