0

I am currently looking for ways that I could actually print information to the jTextpane when I run the following code. When I press the button to run it, the program actually hang and no display for the output. Is there anyway to go round it or to fix it?

 private void ScannetworkActionPerformed(java.awt.event.ActionEvent evt) {  
 Process p = null;
        try {
            p = Runtime.getRuntime().exec("ipconfig /all");
    } catch (IOException ex) {
        Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
    }

    try {
        p.waitFor();
    } catch (InterruptedException ex) {
        Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
    }
    BufferedReader buf = new BufferedReader(new InputStreamReader(
        p.getInputStream()));
String line = "";
String output = "";

try {
    while ((line = buf.readLine()) != null) {
        output += line + "\n";
    }     } catch (IOException ex) {
        Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
        }
    nninfo.setText(output);        

Screenshot: enter image description here

1 Answers1

1

You will need to execute the process in a separate thread, otherwise it will be executed in the UI-Thread and will block any refresh events as long as the process is running. In swing this is usually done by using a SwingWorker (just google for it and you'll probably find some nice tutorials).

Furthermore Process.waitFor() will wait for the process to finish and after that you'll read the contents of the process' output. That is you'll not get any updates as long as the process is running. To update your UI with information from the running process you have to read the data from the process' input stream prior to waiting for the process to finish. Maybe this question and the accepted answer will help you to figure out how to do this.

This is what your SwingWorker might look like. I haven't tested it, but it should give you some idea:

public class ScannetworkWorker
    extends SwingWorker<String, String>
{

  private final JTextPane mOutputPane;

  public ScannetworkWorker(JTextPane aOutputPane)
  {
    super();
    mOutputPane = aOutputPane;
  }

  @Override
  protected String doInBackground() throws Exception
  {
    Process p = null;
    try
    {
      p = Runtime.getRuntime().exec("ipconfig /all");
    }
    catch (IOException ex)
    {
      Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
    }

    BufferedReader buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = "";
    String output = "";

    try
    {
      while ((line = buf.readLine()) != null)
      {
        publish(line);
        output += line + "\n";
      }
    }
    catch (IOException ex)
    {
      Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
    }

    try
    {
      p.waitFor();
    }
    catch (InterruptedException ex)
    {
      Logger.getLogger(home.class.getName()).log(Level.SEVERE, null, ex);
    }

    return output;
  }

  @Override
  protected void process(List<String> aChunks)
  {
    final String intermediateOutput = aChunks.stream().collect(Collectors.joining("\n"));
    final String existingText = mOutputPane.getText();

    final String newText = existingText + "\n" + intermediateOutput;

    mOutputPane.setText(newText);
  }

}
dpr
  • 10,591
  • 3
  • 41
  • 71
  • Thanks for the suggestion, googling that to dig something out. What if the command that i run in terminal which have a non stop output lets say some command that would keep on refresh itself on the terminal screen, how would i display it on the jtextpanel? – Joco Tan Guan Min Mar 05 '17 at 13:52
  • It's basically as already said. If you loop over the process' output and the process does not terminate, it will simply stay in the loop and you can update your UI using `SwingWorker.publish` and `SwingWorker.process` as mentioned [here](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html). The important thing is that you update the UI elements in the respective methods of `SwingWorker` that are called on the event dispatch thread. Otherwise your UI will become unresponsive and you will produce race conditions between the different threads of your application. – dpr Mar 05 '17 at 19:33
  • Thanks for the comment. I am looking at my code and how to using the SwingWorker, but a little hard time to understand it. – Joco Tan Guan Min Mar 06 '17 at 08:56
  • I can imagine. Multi threading is not necessarily the first think I'd recommend for someone relatively new to programming... – dpr Mar 06 '17 at 09:13
  • well i am actually confused with how to use the swingworker, specially with how to apply on the ProcessBuilder and then the output. – Joco Tan Guan Min Mar 06 '17 at 09:21
  • Thanks, i used the code to create another class and call it into the main one. At least it don't hang when i try to issue large command or command that take long time to load. However, if i issue command that will create a process that is non-stop eg: lets say ping 8.8.8.8 -t, it will hangs and never allow me to further interact with it. – Joco Tan Guan Min Mar 06 '17 at 13:31
  • How do you want to interact? Cancel? You will need to implement something inside your `SwingWorker` to cancel the running process and trigger this by some action in your code. – dpr Mar 06 '17 at 13:33
  • More to like run the command for 10 sec and then stop it so that i could output. Something like that. What kind of function or command that i could implement? If can, would keep it running at the background if possible. – Joco Tan Guan Min Mar 06 '17 at 13:48
  • I think you did not quite use the `SwingWorker` correctly. Take a look at https://java-demos.blogspot.de/2013/10/a-simple-swingworker-example-to-save.html – dpr Mar 06 '17 at 13:54
  • I admit with that, it is a difficult task to understand the concurrent part of java. After reading the links you gave me, I understand the concept. But implementation part is still a challenge. Still trying to get 2 task to run at the same time, so meaning that the (eg: ping 8.8.8.8.-t) are running and the jtextpane are printing line by line of the result instead of wait for it to finish and then print the result. Watched the youtube tutorial but most of them are doing the jprogressbar. – Joco Tan Guan Min Mar 06 '17 at 18:05
  • Great to hear you got it working. I just found an example on how to use `SwingWorker` here on SoF: https://stackoverflow.com/documentation/swing/3431/swing-workers-and-the-edt – dpr Mar 07 '17 at 07:36
  • Thank you, it is a good example for learning. I found that what caused that not to work was instead of calling the process.execute(), i called the process.doinbackground(); which then spend me hours to figure out the mistake i did for calling the class... feeling so stupid... – Joco Tan Guan Min Mar 07 '17 at 07:40