Search code examples
javajavafxterminallocal

Create a Local Terminal Emulator App in JavaFX


How would I go about creating a local terminal in textarea type of app in javafx. Thank you in advance!

try {
            String[] comm = new String[] {"/bin/bash", "-c", "open -a Terminal \"`pwd`\""};
            Runtime.getRuntime().exec(comm);
        } 
        
        catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

Solution

  • Here is a rough start.

    One key component is to use Process.

    Process process = Runtime.getRuntime().exec("command-here")
    

    Another key component is to read the process return data.

    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line = "";
    while ((line = reader.readLine()) != null) 
    {
        System.out.println(line);
        
    }  
    

    Instead of just printing the line, we will use Task and its message property to print to our TextArea.

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javafx.application.Application;
    import javafx.concurrent.Task;
    import javafx.scene.Scene;
    import javafx.scene.control.TextArea;
    import javafx.scene.input.KeyCode;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    
    /**
     * JavaFX App
     */
    public class App extends Application 
    {   
        TextArea textArea = new TextArea("ping www.google.com");
        
        @Override
        public void start(Stage stage) 
        {
            textArea.setOnKeyPressed((t) -> {
                try 
                {
                    if(t.getCode() == KeyCode.ENTER)
                    {
                        String[] splitText = textArea.getText().split("\n");
                        Process process = Runtime.getRuntime().exec(splitText[splitText.length -1]);
                        Task<Void> task = printResults(process);
                        task.messageProperty().addListener((obs, oldText, newText)->{
                            textArea.appendText(newText + "\n");
                        });
                        task.setOnSucceeded((workerStateEvent) -> {
                            textArea.setEditable(true);
                        });
                        Thread thread = new Thread(task);
                        thread.setDaemon(true);
                        thread.start();
                    }
                } catch (IOException ex) 
                {
                    Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
                }
            });
            
            var scene = new Scene(new StackPane(textArea), 640, 480);
            stage.setScene(scene);
            stage.show();
        }
    
        public static void main(String[] args) 
        {
            launch();
        }
    
        Task<Void> printResults(Process process)
        {
            textArea.setEditable(false);
            Task<Void> task = new Task<Void>() 
            {
                @Override protected Void call(){
                    try 
                    {
                        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                        String line = "";
                        while ((line = reader.readLine()) != null) 
                        {
                            updateMessage(line);
                        }   
                    } 
                    catch (IOException ex) 
                    {
                        Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
                    }
    
                    return null;
                }
            };
                
            return task ;
        }   
    }
    

    enter image description here