最基本原理
通过循环结构控制进度条的更新,并利用特定的输出控制符(例如\r
)实现动态更新进度条的效果。在循环中,根据任务进度的变化,动态计算并更新进度条的长度和百分比显示,同时通过模拟任务执行时间(例如使用 sleep
函数或命令)来控制进度条的变化速度。
C++实现
运行效果
代码
#include <iostream>
#include <iomanip> // 用于控制输出格式
#include <thread> // 用于线程休眠
#include <chrono> // 用于时间单位
void showProgressBar(int durationMs) {
int progressBarWidth = 40; // 进度条总宽度
float progress = 0.0f; // 当前任务进度百分比
// 打印初始进度条和百分比
std::cout << "Progress: ";
std::cout << "[" << std::setw(progressBarWidth) << "]" << " 0%" << std::flush;
for (int i = 0; i <= progressBarWidth; ++i) {
// 更新进度条
std::cout << "\rProgress: ["; // 使用 \r 回到行首
for (int j = 0; j < i; ++j) {
std::cout << "="; // 已完成部分
}
std::cout << ">" << std::setw(progressBarWidth - i) << "]"; // 当前进度位置
// 计算当前进度百分比
progress = static_cast<float>(i) / progressBarWidth * 100.0f;
std::cout << " " << std::setw(3) << static_cast<int>(progress) << "%" << std::flush;
// 模拟任务执行时间
std::this_thread::sleep_for(std::chrono::milliseconds(durationMs / progressBarWidth));
}
std::cout << std::endl; // 输出换行,任务完成后换行显示
}
int main() {
int durationMs = 2000; // 模拟任务执行时间(毫秒)
std::cout << "Starting task..." << std::endl;
showProgressBar(durationMs); // 调用显示进度条的函数
std::cout << "Task completed!" << std::endl;
return 0;
}
代码详解
这段代码实现了一个简单的自左往右的进度条效果。首先,在 showProgressBar
函数中,我们定义了进度条的总宽度 progressBarWidth
和当前任务进度的百分比 progress
。在主循环中,我们通过循环逐步增加进度条的长度,每次循环都会更新进度条的显示和任务进度百分比。具体实现细节如下:
-
初始化进度条和百分比
- 打印初始的进度条,使用
std::setw
控制输出宽度,确保进度条和百分比的对齐。 - 初始进度为 0%,表示任务尚未开始。
- 打印初始的进度条,使用
-
更新进度条
- 在每次循环中,通过输出
\r
回到行首,并根据当前进度更新进度条的显示。 - 输出已完成部分的
=
符号和当前进度位置的>
符号,以及剩余部分的空格。 - 使用
std::flush
立即刷新输出流,确保进度条的动态显示。
- 在每次循环中,通过输出
-
更新任务进度百分比
- 根据当前循环次数计算任务的完成百分比,并在进度条右侧显示百分比数字。
-
模拟任务执行时间
- 使用
std::this_thread::sleep_for
模拟任务执行时间,通过将总执行时间均匀分配到每个循环中,实现进度条的动态更新效果。
- 使用
Python实现
运行效果
代码
(Python真的简洁!!!)
import sys
import time
def show_progress_bar(duration_sec):
progress_bar_width = 40
progress = 0.0
sys.stdout.write("Progress: [" + " " * progress_bar_width + "] 0%")
sys.stdout.flush()
for i in range(progress_bar_width + 1):
# 更新进度条
sys.stdout.write("\rProgress: [" + "=" * i + ">" + " " * (progress_bar_width - i) + "]")
# 计算当前进度百分比
progress = float(i) / progress_bar_width * 100.0
sys.stdout.write(" {:.0f}%".format(progress))
sys.stdout.flush()
# 模拟任务执行时间
time.sleep(duration_sec / progress_bar_width)
print("\nTask completed!")
if __name__ == "__main__":
duration_sec = 2.0 # 模拟任务执行时间(秒)
print("Starting task...")
show_progress_bar(duration_sec)
代码详解
-
初始化进度条和百分比
- 使用
sys.stdout.write
输出初始的进度条,通过乘以空格的方式控制进度条的长度,并使用sys.stdout.flush
立即刷新输出流,确保进度条的显示。 - 初始进度为 0%,表示任务尚未开始。
- 使用
-
更新进度条
- 在每次循环中,通过输出
\r
回到行首,并根据当前进度更新进度条的显示。 - 使用
sys.stdout.write
更新已完成部分的=
符号、当前进度位置的>
符号,以及剩余部分的空格,同时输出百分比数字。 - 使用
sys.stdout.flush
立即刷新输出流,确保进度条的动态显示。
- 在每次循环中,通过输出
-
更新任务进度百分比
- 根据当前循环次数计算任务的完成百分比,并在进度条右侧显示百分比数字。
-
模拟任务执行时间
- 使用
time.sleep
模拟任务执行时间,通过将总执行时间均匀分配到每个循环中,实现进度条的动态更新效果。
- 使用
Shell实现
运行效果
代码
#!/bin/bash
show_progress_bar() {
duration_sec=$1
progress_bar_width=40
progress=0.0
# 打印初始进度条和百分比
echo -n "Progress: ["
for ((i = 0; i < progress_bar_width; i++)); do
echo -n " "
done
echo -n "] 0%"
for ((i = 0; i <= progress_bar_width; i++)); do
# 更新进度条
echo -ne "\rProgress: ["
for ((j = 0; j < i; j++)); do
echo -n "="
done
echo -n ">"
for ((j = i; j < progress_bar_width; j++)); do
echo -n " "
done
# 计算当前进度百分比
progress=$(awk "BEGIN {printf \"%.0f\", $i / $progress_bar_width * 100}")
echo -n "] $progress%"
# 模拟任务执行时间
sleep $(awk "BEGIN {printf \"%.3f\", $duration_sec / $progress_bar_width}")
done
echo # 输出换行,任务完成后换行显示
echo "Task completed!"
}
# 设置模拟任务执行时间(秒)
duration_sec=2.0
echo "Starting task..."
show_progress_bar "$duration_sec"
代码详解
-
初始化进度条和百分比
- 使用
echo -n
和printf
打印初始的进度条,通过打印空格的方式控制进度条的长度,然后使用echo -n
打印初始的百分比。 - 初始进度为 0%,表示任务尚未开始。
- 使用
-
更新进度条
- 在每次循环中,使用
echo -ne
和printf
更新已完成部分的=
符号、当前进度位置的>
符号,以及剩余部分的空格,同时输出百分比数字。 - 使用
awk
计算当前进度百分比,并输出。
- 在每次循环中,使用
-
模拟任务执行时间
- 使用
sleep
命令模拟任务执行时间,通过将总执行时间均匀分配到每个循环中,实现进度条的动态更新效果。
- 使用