Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Progress bar in Swing (Java) for command tools

I have several C/C++ command line tools that I'm wrapping with Java.Swing as GUI. The command line tools can take minutes to hours. Progress bar seems like a good idea to keep users sane. I'm also thinking it might be nice to wrap a GUI for the progress bar, instead of just using system out. But how?

I'm thinking the command line tools can write percents to stderr and I can somehow read it in java. Not exactly sure what the mechanics for this would be. I'm also not clear on asynchronous display (learned a bit about invokeLater() ). New to Java, and would appreciate general suggestions as well. Thanks.

--- update ---

Thanks everyone for your suggestions. Here's the resulting code.

private void redirectSystemStreams() {
    OutputStream out_stderr = new OutputStream() {
      @Override
      public void write(final int b) throws IOException {
        update(String.valueOf((char) b));
      }
      @Override
      public void write(byte[] b, int off, int len) throws IOException {
        update(new String(b, off, len));
      }
      @Override
      public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
      }
    };
    System.setErr(new PrintStream(out_stderr, true));
}

private void update(final String inputText) {
    int value = 20; //parse inputText; make sure your executable calls fflush(stderr) after each fprintf().
    jProgressBar.setValue(value);

    /* Also one can redirect to a textpane
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        //update jTextPane with inputText
      }
    });
    */
}
like image 722
paulan Avatar asked Jan 21 '23 00:01

paulan


2 Answers

That's seems very fragile, better would be to communicate via sockets in a well established protocol or with some sort of RCP ( perhaps Google's protobuf ) or even webservices.

If you still insists you can launch a process in Java with ProcessBuilder that will give you a Process reference of which you can get the InputStream to read the standard output, but again, that seems very fragile to me.

I hope this helps.

like image 167
OscarRyz Avatar answered Jan 22 '23 14:01

OscarRyz


For the progress bar part of your problem you can do something like the following. Note that this is just an example to illustrate the point.

Basically, a thread is created to do the work. Presumably this Runner thread will be interacting with your C/C++ code to get its progress. It then calls update on the Progress Bars Dialog class.

   import java.awt.BorderLayout;
   import java.awt.Dimension;
   import javax.swing.JDialog;
   import javax.swing.JFrame;
   import javax.swing.JLabel;
   import javax.swing.JPanel;
   import javax.swing.JProgressBar;

  public class Main {

   private int value;
   private Progress pbar;

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

   public Main() {        

     pbar = new Progress();
     Thread t = new Thread(new Runner());
     t.start();

  }

  class Progress extends JDialog {

    JProgressBar pb;
    JLabel label;

    public Progress() {
        super((JFrame) null, "Task In Progress");
        pb = new JProgressBar(0, 100);
        pb.setPreferredSize(new Dimension(175, 20));
        pb.setString("Working");
        pb.setStringPainted(true);
        pb.setValue(0);


        label = new JLabel("Progress: ");

        JPanel panel = new JPanel();
        panel.add(label);
        panel.add(pb);
        add(panel, BorderLayout.CENTER);
        pack();
        setVisible(true);
    }

    public void update(){
        pb.setValue(value);

        if(value >= 100){
            this.setVisible(false);
            this.dispose();
        }
    }
}

class Runner implements Runnable {

    public void run() {
        for (int i = 0; i <= 100; i++) {
            value++;
            pbar.update();
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
            }
        }
     }
   }
 }
like image 21
Vincent Ramdhanie Avatar answered Jan 22 '23 13:01

Vincent Ramdhanie