我们在使用wget等软件时,会看到诸如下面这样的进度条的提示。
本文我们介绍如何实现一个这样的进度条。
简单的进度条
一般我们执行输出操作后,都是在console框中的内容后面进行追加。但是进度条却不是追加的效果,而是覆盖。所以我们需要找到覆盖当前行的方案——这就是"\r"——会将光标重新定位到该行头部。这样我们就可以重新写这行的内容——只要我们新写入的内容长于等于原来的内容,就会形成覆盖效果。
这个进度条有几部分组成:
- [ 表示进度条的左边框
- = 表示进度条行进到的位置
- (空格)表示进度条尚未行进到的位置
- ] 表示进度条的右边框
- xx% 表示进度的数值
拆分完后,我们只要定时使用\r将光标定位到行头,然后按照当前进度调整=和(空格)的数量就可以形成进度条了。
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void showProgressBar(int duration) {
const int barWidth = 50;
cout << "[";
for (int i = 0; i < barWidth; ++i) {
cout << " ";
}
cout << "]" << flush;
for (int i = 0; i <= barWidth; ++i) {
cout << "\r[";
for (int j = 0; j < i; ++j) {
cout << "=";
}
for (int j = i; j < barWidth; ++j) {
cout << " ";
}
cout << "] " << int((i / (float)barWidth) * 100.0) << "%" << flush;
this_thread::sleep_for(chrono::milliseconds(duration / barWidth));
}
cout << endl;
}
int main() {
int duration = 5000; // 进度条持续时间(毫秒)
showProgressBar(duration);
return 0;
}
代码地址
https://github.com/f304646673/cpulsplus/tree/master/console_ui/progress/single
带色彩的进度条
如果需要控制颜色,我们可以使用ANSI 转义码来实现。
我们现在要求进度未到100%时,进度条使用红色;如果到了100%,就是用绿色。同时进度也加粗表示。
这儿有个问题,就是要控制颜色区域。比如上图中表示进度条左右边框的[]不能变色,那么只能把颜色控制在变动中的进度条和最后的比例数字上。
比如我们要显示绿色的=,可以使用下面的代码
cout << "\033[32m" << "=" << "\033[0m";
"\033[32m"
表示后面输出的颜色是绿色;"\033[0m"
表示后面输出的颜色是默认设置颜色。
完整的代码如下
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void showProgressBar(int duration) {
const int barWidth = 50;
const string red = "\033[31m"; // 红色
const string green = "\033[32m"; // 绿色
const string reset = "\033[0m"; // 重置颜色
const string bold = "\033[1m"; // 加粗
cout << "[";
for (int i = 0; i < barWidth; ++i) {
cout << " ";
}
cout << "]" << flush;
for (int i = 0; i <= barWidth; ++i) {
cout << "\r[";
for (int j = 0; j < i; ++j) {
if (i == barWidth) {
cout << green << "=" << reset;
} else {
cout << red << "=" << reset;
}
}
for (int j = i; j < barWidth; ++j) {
cout << " ";
}
cout << "] ";
if (i == barWidth) {
cout << green << bold;
} else {
cout << red;
}
cout << int((i / (float)barWidth) * 100.0) << "%" << reset << flush;
this_thread::sleep_for(chrono::milliseconds(duration / barWidth));
}
cout << endl;
}
int main() {
int duration = 5000; // 进度条持续时间(毫秒)
showProgressBar(duration);
return 0;
}
代码地址
https://github.com/f304646673/cpulsplus/tree/master/console_ui/progress/color