Reputation: 3700
I have a program processing a large, lengthy job. I know the size of the task up front so I display a progress bar. Yet the individual sub-tasks can take a long time, so in the end the progress bar can also stay idle for a long time, making it look like a program has stalled.
For the inpatient users out there I though I might include an indicator, which just continuously spins a simple ASCII animation, reassuring them that theres still some computing going on. I have a problem combining it with the progress bar updates though - if I use a carriage return it displays where my progress bar should be and I'd rather have it befor the PB, something like this:
Busy /
0 25 50 75 100%
|-----|-----|-----|-----|
[*****************
The code:
public class Test {
public static void main(String[] args) {
try {
int barLength = 100;
int jobLength = 501;
double stepSize = (double) barLength / (double) jobLength;
String message = "Busy";
RotatingProgressBar progressBar = new RotatingProgressBar(message);
progressBar.start();
System.out
.println("0 25 50 75 100%");
System.out
.println("|------------------------|------------------------|------------------------|------------------------|");
for (int i = 0; i <= jobLength; i++) {
Thread.sleep(100);
double progress = (stepSize * i) / barLength;
updateProgress(progress, barLength);
}
progressBar.setShowProgress(false);
} catch (Exception e) {
e.printStackTrace();
}
}// END: main
static void updateProgress(double progressPercentage, int barLength) {
System.out.print("\r[");
int i = 0;
for (; i < (int) (progressPercentage * (barLength - 1)); i++) {
System.out.print("*");
}
for (; i < barLength - 1; i++) {
System.out.print(" ");
}
System.out.print("]");
}// END: updateProgress
static class RotatingProgressBar extends Thread {
private final String anim = "|/-\\";
private boolean showProgress = true;
private String message;
public RotatingProgressBar(String message) {
this.message = message;
}
public void run() {
int i = 0;
while (showProgress) {
System.out.print("\r");
System.out.print(message + anim.charAt(i++ % anim.length()));
try {
Thread.sleep(10);
} catch (Exception e) {
// do nothing
}// END: try-catch
}// END: while
}// END: run
public void setShowProgress(boolean showProgress) {
this.showProgress = showProgress;
}
// public void setCarriageColumn(int column) {
// this.column = column;
// }
}// END: class
}// END: class
Upvotes: 2
Views: 610
Reputation: 3700
I think I solved this, inspired by @Stefan Lindenberg and @nafas. I merged two methods into one, the busy indicator spins continuously as the last character of the progress bar, which I update with a progress:
class ProgressBar extends Thread {
private static final String anim = "|/-\\";
private boolean showProgress;
double progressPercentage;
private final int barLength;
public ProgressBar(int barLength) {
this.barLength = barLength;
this.showProgress = true;
this.progressPercentage = 0;
}
public void run() {
int i = 0;
while (showProgress) {
String progress = "\r";
int column = (int) (progressPercentage * barLength);
for (int j = 0; j <= column; j++) {
progress += ("*");
}
System.out.print(progress + anim.charAt(i++ % anim.length()));
try {
Thread.sleep(10);
} catch (Exception e) {
// do nothing
}// END: try-catch
}// END: while
}// END: run
public void setShowProgress(boolean showProgress) {
this.showProgress = showProgress;
}
public void setProgressPercentage(double progressPercentage) {
this.progressPercentage = progressPercentage;
}
}// END: class
and this is then used like this:
for (int i = 0; i <= jobLength; i++) {
Thread.sleep(100);
double progress = (stepSize * i) / barLength;
progressBar.setProgressPercentage(progress);
}
Looks ok.
Upvotes: 0
Reputation: 12453
You can use this method to delete chars that have been already printed to System.out:
public void deleteChar(int times) {
for (int i = 0; i < times; i++) {
System.out.print((char) 8);
}
}
But this (and other workarounds) are not going to work in all types of terminals/consoles. This will work in Windows cmd, powershell and most Unix terminals, but it will fail in Eclipse or Netbeans.
Upvotes: 1