开发者

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 inputT开发者_StackOverflowext
      }
    });
    */
}


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.


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) {
            }
        }
     }
   }
 }


// Create a window
JFrame frame = new JFrame("Progress");
// Creates a progress bar and add it to the window
JProgressBar prog = new JProgressBar();
frame.add(prog);
// Run C/C++ application
try {
   Process p = Runtime.getRuntime().exec(new String[]{"filename","arg1","arg2","..."});
   // Get InputStream
   BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
   // Update the progress when recieving output from C/C++
   new java.util.Timer().schedule(new TimerTask(){
       public void run(){
          String str = "";
          while ((str=br.readLine()!=null) {
             prog.setValue(new Integer(str)); // Set Value of Progress Bar
             prog.setString(str+"%"); // Set Value to display (in text) on Progress Bar
          }
       }
   },0,100); // Check every 100 milliseconds
   // Fit the window to its contents and display it
   frame.pack();
   frame.setVisible(true);
 } catch (Exception e) {
    System.out.println("Failed To Launch Program or Failed To Get Input Stream");
 }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜