// ---------------------------------------------------------------------------ProgressBarMthread.h
#ifndef PROGRESSBARMTHREAD
#define PROGRESSBARMTHREAD
#include <unordered_map>
#include <mutex>
class ProgressBarMthread
{
private:
std::unordered_map<std::thread::id, int> mapX;
int startX;
std::mutex mut;
private:
void moveCursor(int x, int y);
void getCursorPosition(int& x, int& y);
public:
ProgressBarMthread();
void displayProgressBar(std::string title, int progress, int total, int barWidth = 100);
~ProgressBarMthread();
};
#endif // !PROGRESSBARMTHREAD
// ---------------------------------------------------------------------------ProgressBarMthread.cpp
#include "ProgressBarMthread.h"
#include <iostream>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <term.h>
#endif
// 移动光标到指定位置
void ProgressBarMthread::moveCursor(int x, int y) {
std::cout << "\033[" << x + 1 << ";" << y + 1 << "H";
}
// 获取光标位置的函数,Windows 版本
void ProgressBarMthread::getCursorPosition(int& x, int& y) {
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
y = csbi.dwCursorPosition.X;
x = csbi.dwCursorPosition.Y;
#else
if (!cur_term) {
int result;
setupterm(nullptr, STDOUT_FILENO, &result);
if (result <= 0) {
return;
}
}
y = tigetnum("cols");
x = tigetnum("lines");
#end
}
ProgressBarMthread::ProgressBarMthread()
: startX(0)
{
int startY;
getCursorPosition(startX, startY);
if (startY != 0)
{
startX++;
}
}
void ProgressBarMthread::displayProgressBar(std::string title, int progress, int total, int barWidth)
{
std::lock_guard<std::mutex> lk(mut);
auto tId = std::this_thread::get_id();
if (mapX.find(tId) == mapX.end())
{
int x = startX + (int)mapX.size();
mapX[tId] = x;
}
float percentage = static_cast<float>(progress) / total;
int progressBarWidth = static_cast<int>(percentage * barWidth);
moveCursor(mapX[tId], 0);
std::cout << title << " ";
std::cout << "[";
for (int i = 0; i < barWidth; ++i) {
if (i < progressBarWidth) {
std::cout << "=";
}
else {
std::cout << " ";
}
}
std::cout << "] " << percentage * 100.0 << "% ";
std::cout.flush();
}
ProgressBarMthread::~ProgressBarMthread()
{
int x = startX + (int)mapX.size();
moveCursor(x, 0);
}
// ---------------------------------------------------------------------------main.cpp
// 使用示例
#include "ProgressBarMthread.h"
void threadFunc(ProgressBarMthread& proBar)
{
for (int i = 0; i < 20; ++i)
{
// 随机睡眠一段时间,模拟大量数据处理
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> distribution(0, 2);
int x = distribution(gen);
std::this_thread::sleep_for(std::chrono::seconds(x));
// 显示进度
proBar.displayProgressBar("title", i + 1, 20);
}
}
int main() {
std::cout << "befor befor" << std::endl;
std::cout << "befor befor";
{
ProgressBarMthread proBar;
std::thread t1(threadFunc, std::ref(proBar));
std::thread t2(threadFunc, std::ref(proBar));
std::thread t3(threadFunc, std::ref(proBar));
t1.join();
t2.join();
t3.join();
}
std::cout << "after after" << std::endl;
std::cout << "after after" << std::endl;
return 0;
}
![](https://uploadfiles.nowcoder.com/images/20240125/95673566_1706182558024/079F4FB55B755F6F198BEE97D7C95390)
![](https://uploadfiles.nowcoder.com/images/20240125/95673566_1706182563808/19EE203F0229AAE4B91567BFF25442E5)
![](https://uploadfiles.nowcoder.com/images/20240125/95673566_1706182570677/E1A735C5228622A1F2B0A4F4D6338E1F)
![](https://uploadfiles.nowcoder.com/images/20240125/95673566_1706182577129/8EE1A140D57287155C2239319DC8E2EC)
#c++##进度条#