
Java手搓进度条实现:从简单到优雅
Java手搓进度条实现:从简单到优雅
在Java开发中,我们经常需要处理耗时操作,并希望向用户展示进度。本文将介绍几种实现进度条的方法,从最简单的文本输出到美观的进度条显示。
一、最简单的进度显示
当我们刚开始学习编程时,可能会想到最简单的方式:在循环中输出当前进度。
public class Loop {
public static void main(String[] args) {
int size = 500;
System.out.println("开始运行");
for (int i = 0; i < size; i++) {
doSth();
System.out.print("进度:" + (i + 1) + "/" + size + "\r");
}
System.out.println();
System.out.println("结束运行");
}
private static void doSth() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这种方式的特点:
- 使用
\r
回车符将光标移到行首,实现覆盖输出 - 简单直观,容易理解
- 显示效果不够美观,只是简单的文本
二、使用进度条类实现更美观的显示
为了获得更美观的进度显示,我们可以创建一个专门的进度条类。下面是一个简单的进度条实现:
public class ProgressBar {
private final int total;
private final int width;
private int current;
private Style style;
private final static Style STYLE_1 = new Style("#", " ", "");
private final static Style STYLE_2 = new Style("#", "=", "");
private final static Style STYLE_3 = new Style("=", " ", ">");
public ProgressBar(int total, int width, int style) {
this.total = total;
this.width = width;
this.current = 0;
if (style == 1) {
this.style = STYLE_1;
} else if (style == 2) {
this.style = STYLE_2;
} else {
this.style = STYLE_3;
}
}
public void start() {
System.out.println("\n开始执行任务...");
}
public void finish() {
System.out.println("\n任务执行结束...");
}
public void update(int progress) {
this.current = progress;
print();
}
private void print() {
double percentage = (double) current / total;
int progressMarks = (int) (percentage * width);
StringBuilder bar = new StringBuilder();
bar.append(String.format("当前进度: %3d%% [", (int) (percentage * 100)));
boolean firstRight = true;
for (int i = 0; i < width; i++) {
if (i < progressMarks) {
bar.append(style.leftStr);
} else {
if (firstRight) {
bar.append(style.leftEndStr);
firstRight = false;
}
bar.append(style.rightStr);
}
}
bar.append("]");
System.out.print("\r" + bar);
if (percentage >= 1) {
finish();
}
}
@Getter
private static class Style {
private String leftStr;
private String rightStr;
private String leftEndStr;
public Style(String leftStr, String rightStr, String leftEndStr) {
this.leftStr = leftStr;
this.rightStr = rightStr;
this.leftEndStr = leftEndStr;
}
}
}
这个进度条类的特点:
- 支持自定义进度条宽度
- 提供多种样式选择
- 显示百分比和进度条图形
- 自动处理开始和结束提示
三、使用进度条类展示进度
有了进度条类,我们可以这样使用它:
public class LoopProgress {
public static void main(String[] args) {
int size = 500;
ProgressBar progressBar = new ProgressBar(size, 60, 2);
System.out.println("开始运行");
for (int i = 0; i < size; i++) {
doSth();
progressBar.update(i + 1);
}
}
private static void doSth() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这种方式的特点:
- 代码更加模块化,进度条逻辑与业务逻辑分离
- 显示效果更加美观,有图形化的进度条
- 可以轻松扩展更多功能
四、进度条实现的深入解析
1. 进度条的核心原理
进度条的核心原理是利用控制台的回车符\r
,将光标移到行首,然后覆盖输出新的进度信息。这样就能在同一行更新进度,而不是不断打印新行。
2. 进度条样式的设计
在ProgressBar
类中,我们使用了内部类Style
来定义不同的进度条样式:
private static class Style {
private String leftStr; // 已完成部分的字符
private String rightStr; // 未完成部分的字符
private String leftEndStr; // 进度条末尾的字符
}
通过组合这些字符,我们可以创建不同风格的进度条:
- 样式1:
[#### ]
- 样式2:
[####====]
- 样式3:
[====> ]
3. 进度计算与显示
进度条的核心计算逻辑在print()
方法中:
private void print() {
double percentage = (double) current / total;
int progressMarks = (int) (percentage * width);
StringBuilder bar = new StringBuilder();
bar.append(String.format("当前进度: %3d%% [", (int) (percentage * 100)));
boolean firstRight = true;
for (int i = 0; i < width; i++) {
if (i < progressMarks) {
bar.append(style.leftStr);
} else {
if (firstRight) {
bar.append(style.leftEndStr);
firstRight = false;
}
bar.append(style.rightStr);
}
}
bar.append("]");
System.out.print("\r" + bar);
if (percentage >= 1) {
finish();
}
}
这段代码:
- 计算当前进度的百分比
- 根据百分比和进度条宽度计算已完成的标记数量
- 构建进度条字符串,包括百分比和图形化进度条
- 使用
\r
回车符覆盖输出进度条 - 当进度达到100%时,调用
finish()
方法
五、进度条的扩展与优化
基于上述实现,我们可以进一步扩展和优化进度条:
- 添加颜色支持:使用ANSI转义序列为进度条添加颜色
- 添加速度显示:显示每秒处理的项目数
- 添加预计剩余时间:根据当前速度计算预计完成时间
- 支持多线程:在多线程环境中安全地更新进度
- 支持进度条嵌套:显示子任务的进度
六、总结
通过本文的介绍,我们了解了从简单的文本进度显示到美观的进度条实现的演进过程。一个好的进度条不仅能够提供直观的进度反馈,还能提升用户体验。
在实际开发中,我们可以根据项目需求选择合适的进度条实现,或者基于本文的代码进行定制化开发,以满足特定的显示需求。
希望本文对您有所帮助,欢迎在评论区分享您的想法和经验!
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员橙子
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果