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.
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
How to Upload File Using Selenium Webdriver in Java
Antlr: Is There a Simple Example
Initial Bytes Incorrect After Java Aes/Cbc Decryption
Hibernate Annotations - Which Is Better, Field or Property Access
What Is Suppresswarnings ("Unchecked") in Java
How to Convert Java String into Byte[]
Sqlexception: No Suitable Driver Found for Jdbc:Derby://Localhost:1527
Concurrent Modification Exception
File Path to Resource in Our War/Web-Inf Folder
Invalidkeyexception Illegal Key Size
How to Configure Port for a Spring Boot Application
How to Create a Rest Client for Java
Compiling a Java Program into an Executable
How to Extract a Substring Using Regex
How to Get Current Moment in Iso 8601 Format with Date, Hour, and Minute
How to Resolve Java Unknownhostkey, While Using Jsch Sftp Library