Visualizza indeterminata JProgressBar mentre viene eseguito il file batch

Ho navigato SO e google per un po ‘ora per una risposta a questa domanda, ma non riesco a trovarne uno che funzioni davvero. Inizierò dall’inizio:

Ho creato una class Java con un metodo che esegue un file batch in background (la finestra di comando non appare). Il programma funziona alla grande, tranne che sarebbe un po ‘confuso per l’utente finale, dal momento che il file batch richiede un po’ di tempo per essere completato – l’utente non saprà se il programma è ancora in esecuzione o meno. Dopo che lo script batch termina l’esecuzione, viene visualizzata una finestra di dialogo che indica che è stata completata, ma per il periodo di tempo che intercorre tra l’esecuzione del metodo e la finestra di dialogo, sembra che il programma non stia facendo nulla.

Quindi, ecco la mia domanda: mi piacerebbe molto visualizzare un nuovo frame con un’area di testo che mostra l’output del file batch. Tuttavia, capisco che questo è molto difficile da fare senza creare file temporanei, scrivendoli, leggendo da loro e così via. Preferirei evitarlo, se ansible. Pertanto, ho deciso che potrebbe essere meglio visualizzare un JProgressBar indeterminato mentre il processo è in esecuzione e chiuderlo al termine del processo. Sfortunatamente, non credo che Swing possa gestirlo in quanto richiederebbe l’esecuzione di più processi contemporaneamente. Ho sentito parlare di SwingWorker ma non sono esattamente sicuro di come sarebbe stato usato in questo caso. Ho il seguente SSCCE, che funziona, ma non ha la barra di avanzamento implementata.

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!"); } } 

Mentre p.waitFor () attende il processo, non c’è niente sullo schermo. Voglio solo qualcosa che mostri all’utente che un processo è ancora in esecuzione. Pensieri? Grazie!

È ansible eseguire un ProcessBuilder sullo sfondo di un SwingWorker , come mostrato di seguito, per ottenere sia l’ output che una barra di avanzamento.

Immagine

 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 actionPerformsd(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(); } }); } }