带有占用指示器的命令行进度条
Command-line Progress bar with occupied indicator
我有一个程序正在处理一项庞大而冗长的工作。我预先知道任务的大小,所以我显示了一个进度条。
但是个别的子任务可能会耗费很长时间,所以最后进度条也可以闲置很久,看起来像是程序停滞了。
对于那里的住院用户,我可能会包括一个指示器,它只是不断地旋转一个简单的 ASCII 动画,让他们放心,仍然有一些计算在进行。
不过,我在将它与进度条更新结合起来时遇到了问题 - 如果我使用回车 return,它会显示我的进度条应该在的位置,我宁愿在 PB 之前使用它,如下所示:
Busy /
0 25 50 75 100%
|-----|-----|-----|-----|
[*****************
代码:
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
您可以使用此方法删除已经打印到 System.out:
的字符
public void deleteChar(int times) {
for (int i = 0; i < times; i++) {
System.out.print((char) 8);
}
}
但是这个(和其他解决方法)并不适用于所有类型的 terminals/consoles。这将在 Windows cmd、powershell 和大多数 Unix 终端中工作,但在 Eclipse 或 Netbeans 中将失败。
我想我解决了这个问题,受到@Stefan Lindenberg 和@nafas 的启发。我将两种方法合并为一种,忙碌指示器作为进度条的最后一个字符不断旋转,我用进度更新它:
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
然后像这样使用:
for (int i = 0; i <= jobLength; i++) {
Thread.sleep(100);
double progress = (stepSize * i) / barLength;
progressBar.setProgressPercentage(progress);
}
看起来不错。
我有一个程序正在处理一项庞大而冗长的工作。我预先知道任务的大小,所以我显示了一个进度条。 但是个别的子任务可能会耗费很长时间,所以最后进度条也可以闲置很久,看起来像是程序停滞了。
对于那里的住院用户,我可能会包括一个指示器,它只是不断地旋转一个简单的 ASCII 动画,让他们放心,仍然有一些计算在进行。 不过,我在将它与进度条更新结合起来时遇到了问题 - 如果我使用回车 return,它会显示我的进度条应该在的位置,我宁愿在 PB 之前使用它,如下所示:
Busy /
0 25 50 75 100%
|-----|-----|-----|-----|
[*****************
代码:
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
您可以使用此方法删除已经打印到 System.out:
的字符 public void deleteChar(int times) {
for (int i = 0; i < times; i++) {
System.out.print((char) 8);
}
}
但是这个(和其他解决方法)并不适用于所有类型的 terminals/consoles。这将在 Windows cmd、powershell 和大多数 Unix 终端中工作,但在 Eclipse 或 Netbeans 中将失败。
我想我解决了这个问题,受到@Stefan Lindenberg 和@nafas 的启发。我将两种方法合并为一种,忙碌指示器作为进度条的最后一个字符不断旋转,我用进度更新它:
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
然后像这样使用:
for (int i = 0; i <= jobLength; i++) {
Thread.sleep(100);
double progress = (stepSize * i) / barLength;
progressBar.setProgressPercentage(progress);
}
看起来不错。