Display Indeterminate Jprogressbar While Batch File Runs

Display indeterminate JProgressBar while batch file runs

You can run a ProcessBuilder in the background of a SwingWorker, as shown below, to get both output and a progress bar.

image

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<Integer, String> {

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

Adding a indeterminate JProgressBar from an action listener

You do not want to use the SwingWorker but you will have to (or a similar mechanism). You cannot show a JProgressBar while you keep the Event Dispatch Thread (EDT) occupied with your calculations.

You will have to move your calculations to a separate Thread to free the EDT. Then the EDT will be able to show a JProgressBar during the calculations, and remove it when they are finished.

More information on this can be found in the 'Concurrency in Swing' tutorial. An example of a SwingWorker and a JProgressBar can be found here.

Link Progress Bar To Batch File Execution in Install4j

If a progress bar is visible on a screen you can set the progress by calling

context.getProgressInterface().setPercentCompleted(...);

You need a percent value for that purpose. If you don't have such a value, you can set the progress bar to indeterminate by calling

context.getProgressInterface().setIndeterminateProgress(true);

Setting the progress is also possible with the "Set the progress bar" action.

JProgressBar displaying weird orang wave

I didn't look deep into it, but it might be a bug of Nimbus LaF.

Anyway, in order for the orange blocks to stop moving (when its value is set to 100), you also seem to need to call:

prog.setIndeterminate(false);

If you want to "automate" this, you could subclass JProgressBar, e.g.:

prog = new JProgressBar(0, 100) {
public void setValue(int newValue) {
super.setValue(newValue);
if (newValue >= this.getMaximum()) {
this.setIndeterminate(false);
}
}
};
prog.setValue(0);
...

Indeterminate Progress bar wont show

pooyan has the right idea -- do the long running process in a background thread -- but gives the wrong library example, since your program is a Swing program and not an Android program. The canonical answer to this for Swing is to do your long-running task in the doInBackground() method of a SwingWorker.

Please hold while I find a better example...

Something like so:

if (buildpathset == 1) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
progress.setVisible(true);

// create my SwingWorker object
final SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() {
protected Void doInBackground() throws Exception {
// here is my long running task, calling in background
// thread
wiredsync();
return null;
};
};

// this allows me to be notified when the SwingWorker has
// finished
myWorker.addPropertyChangeListener(new PropertyChangeListener() {

@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// if the SwingWorker is done
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
// notify the user
JOptionPane.showMessageDialog(null, "sync complete. ",
null, buildpathset);
setCursor(Cursor.getDefaultCursor());
progress.setVisible(false);

try {
// one way to catch any errors that occur in
// SwingWorker
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}

}
}
});
// run my SwingWorker
myWorker.execute();
} else {
// warning in here later - TO Do
}

For more on this, please check out: Lesson: Concurrency in Swing



Related Topics



Leave a reply



Submit