Mostrar JProgressBar indeterminado mientras se ejecuta el archivo por lotes

He estado navegando SO y google por un tiempo para obtener una respuesta a esta pregunta, pero parece que no puedo encontrar uno que realmente funcione. Comenzaré desde el principio:

Creé una clase Java con un método que ejecuta un archivo por lotes en segundo plano (la ventana de comandos no aparece). El progtwig funciona muy bien, excepto que sería un poco confuso para el usuario final, ya que el archivo por lotes tarda un tiempo en completarse: el usuario no sabrá si el progtwig aún se está ejecutando o no. Una vez que el script por lotes termina de ejecutarse, aparece un mensaje de diálogo que dice que ha finalizado, pero por el período de tiempo entre el momento en que se ejecuta el método y aparece el cuadro de diálogo, parece que el progtwig no está haciendo nada.

Así que aquí está mi pregunta: me gustaría mucho mostrar un nuevo marco con un área de texto que muestra el resultado del archivo por lotes. Sin embargo, entiendo que esto es muy difícil de hacer sin crear archivos temporales, escribirles, leer de ellos, etc. Prefiero evitar eso si es posible. Por lo tanto, he decidido que sería mejor mostrar una JProgressBar indeterminada mientras el proceso se está ejecutando, y cerrarla cuando el proceso haya finalizado. Desafortunadamente, no creo que Swing pueda manejar esto, ya que requeriría ejecutar múltiples procesos a la vez. He oído hablar de un SwingWorker pero no estoy exactamente seguro de cómo se usaría en este caso. Tengo el siguiente SSCCE, que funciona, pero no tiene implementada la barra de progreso.

public myClass(){ public static void main(String[] args){ String[] commands = {"cmd.exe", "/C", "C:\\users\\....\\myBat.bat"}; Process p = Runtime.getRuntime().exec(commands); p.waitFor() JOptionPane.showMessageDialog(null, "Process finished!"); } } 

Mientras p.waitFor () espera el proceso, no hay nada en la pantalla. Solo quiero algo que le muestre al usuario que un proceso aún se está ejecutando. ¿Pensamientos? ¡Gracias!

Puede ejecutar ProcessBuilder en el fondo de un SwingWorker , como se muestra a continuación, para obtener tanto la salida como una barra de progreso.

imagen

 import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.event.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import javax.swing.*; /** * @se http://stackoverflow.com/a/20603012/230513 * @see http://stackoverflow.com/a/17763395/230513 */ public class SwingWorkerExample { private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER); private final JTextArea textArea = new JTextArea(20, 20); private JButton startButton = new JButton("Start"); private JButton stopButton = new JButton("Stop"); private JProgressBar bar = new JProgressBar(); private BackgroundTask backgroundTask; private final ActionListener buttonActions = new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { JButton source = (JButton) ae.getSource(); if (source == startButton) { textArea.setText(null); startButton.setEnabled(false); stopButton.setEnabled(true); backgroundTask = new BackgroundTask(); backgroundTask.execute(); bar.setIndeterminate(true); } else if (source == stopButton) { backgroundTask.cancel(true); backgroundTask.done(); } } }; private void displayGUI() { JFrame frame = new JFrame("Swing Worker Example"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); JPanel panel = new JPanel(); panel.setBorder( BorderFactory.createEmptyBorder(5, 5, 5, 5)); panel.setLayout(new BorderLayout(5, 5)); JScrollPane sp = new JScrollPane(); sp.setBorder(BorderFactory.createTitledBorder("Output: ")); sp.setViewportView(textArea); startButton.addActionListener(buttonActions); stopButton.setEnabled(false); stopButton.addActionListener(buttonActions); JPanel buttonPanel = new JPanel(); buttonPanel.add(startButton); buttonPanel.add(stopButton); buttonPanel.add(bar); panel.add(statusLabel, BorderLayout.PAGE_START); panel.add(sp, BorderLayout.CENTER); panel.add(buttonPanel, BorderLayout.PAGE_END); frame.setContentPane(panel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } private class BackgroundTask extends SwingWorker { private int status; public BackgroundTask() { statusLabel.setText((this.getState()).toString()); } @Override protected Integer doInBackground() { try { ProcessBuilder pb = new ProcessBuilder("ls", "-lR", "/"); pb.redirectErrorStream(true); Process p = pb.start(); String s; BufferedReader stdout = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((s = stdout.readLine()) != null && !isCancelled()) { publish(s); } if (!isCancelled()) { status = p.waitFor(); } p.getInputStream().close(); p.getOutputStream().close(); p.getErrorStream().close(); p.destroy(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(System.err); } return status; } @Override protected void process(java.util.List messages) { statusLabel.setText((this.getState()).toString()); for (String message : messages) { textArea.append(message + "\n"); } } @Override protected void done() { statusLabel.setText((this.getState()).toString() + " " + status); stopButton.setEnabled(false); startButton.setEnabled(true); bar.setIndeterminate(false); } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new SwingWorkerExample().displayGUI(); } }); } }