C++でプログレスバーを表示する6つの方法

C++でプログレスバーを表示するイメージ C++
この記事は約17分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事を読めば、初心者から上級者まで、C++を使ってプログレスバーを表示する方法が理解できるでしょう。

C++は非常に強力なプログラミング言語で、幅広いアプリケーション開発に利用されています。

プログレスバーは、プログラムの進行状況をユーザーに視覚的に表す重要な要素です。

本記事では、基本的なプログレスバーの作成から、カスタマイズや応用例に至るまで、具体的なサンプルコードとともに分かりやすく解説していきます。

●C++とプログレスバーの基本

C++は、汎用プログラミング言語の一つで、高度な抽象化と直接的なハードウェア制御が可能な特徴を持っています。

C++は、そのパフォーマンスの良さから、デスクトップアプリケーション、サーバーサイドアプリケーション、ゲーム開発など、幅広い分野で使用されています。

また、オブジェクト指向プログラミングをサポートしており、再利用可能なコードの作成が可能です。

○C++について

C++でプログラミングを行う際には、クラス、オブジェクト、継承、多様性といったオブジェクト指向の概念を理解することが重要です。

これらの概念を使いこなすことで、保守しやすく、拡張可能なコードを作成することができます。

また、C++は低レベルの操作も可能であり、メモリ管理やポインタなど、ハードウェアに近い部分の制御も行えます。

○プログレスバーとは

プログレスバーは、プログラムの処理進行状況をユーザーに伝えるためのグラフィカルなインターフェースです。

例えば、ファイルのダウンロードやデータの読み込みなど、時間がかかる処理を行っているときに、進行状況を視覚的に表示することで、ユーザーが待機時間の長さを理解しやすくなります。

C++では、様々なライブラリを利用してプログレスバーを実装することが可能です。

GUIツールキットを用いれば、比較的簡単に視覚的に魅力的なプログレスバーを作成することができます。

●C++でプログレスバーを表示する基本的な方法

C++でプログレスバーを表示する最も基本的な方法は、特定のGUIフレームワークを使用することです。

C++には様々なGUIフレームワークがあり、それぞれにプログレスバーを実装するための独自の方法があります。

ここでは、広く使用されているQtフレームワークを例にとって説明します。

Qtは豊富なウィジェットを備えたフレームワークで、プログレスバーの実装も直感的に行えます。

Qtを使用してプログレスバーを作成するには、まずQt Creatorをインストールし、新しいプロジェクトを作成します。

プロジェクトを設定した後、必要なウィジェットをフォームにドラッグ&ドロップしてGUIを構築します。

プログレスバーは「QProgressBar」というウィジェットで提供されています。

○サンプルコード1:シンプルなプログレスバー

下記のサンプルコードは、Qtを使用してシンプルなプログレスバーを表示する基本的な方法を表しています。

#include <QApplication>
#include <QProgressBar>
#include <QMainWindow>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QMainWindow mainWindow;

    QProgressBar *progressBar = new QProgressBar(&mainWindow);
    progressBar->setRange(0, 100);
    progressBar->setValue(50); // 進行状況を50%に設定
    mainWindow.setCentralWidget(progressBar);
    mainWindow.show();

    return app.exec();
}

このコードでは、QProgressBar クラスのインスタンスを作成し、進行状況の範囲を0から100に設定しています。

setValue メソッドを使用して進行状況を50%に設定した後、このプログレスバーをメインウィンドウの中央ウィジェットとして設定しています。

このサンプルを実行すると、半分が進行したプログレスバーが表示されます。

○サンプルコード2:プログレスバーの進行状況を更新する

プログレスバーの進行状況を更新するためには、プログラムの処理に応じてsetValue メソッドを適切に呼び出す必要があります。

下記のサンプルコードは、タイマーを使用して一定間隔でプログレスバーの進行状況を更新する方法を表しています。

#include <QApplication>
#include <QProgressBar>
#include <QMainWindow>
#include <QTimer>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QMainWindow mainWindow;
    QProgressBar *progressBar = new QProgressBar(&mainWindow);
    progressBar->setRange(0, 100);

    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&](){
        int value = progressBar->value();
        if(value < 100) {
            progressBar->setValue(value + 1); // 進行状況を1%増やす
        }
    });
    timer.start(100); // 100ミリ秒ごとに更新

    mainWindow.setCentralWidget(progressBar);
    mainWindow.show();

    return app.exec();
}

このコードでは、QTimer クラスを使用しています。

タイマーがタイムアウトするたび(ここでは100ミリ秒ごと)、ラムダ関数が呼び出され、プログレスバーの値が1%増加します。

値が100に達すると、それ以上増加しなくなります。

●C++でプログレスバーをカスタマイズする方法

C++で作成されたプログレスバーは、見た目や機能面で多様なカスタマイズが可能です。

プログレスバーのカスタマイズは、アプリケーションのユーザーインターフェイスをより魅力的かつ機能的にするために重要です。

カスタマイズを通じて、プログレスバーの色、形状、動きなどを変更し、ユーザーにとってより視覚的に理解しやすいものにすることができます。

○サンプルコード3:カスタマイズされたデザインのプログレスバー

プログレスバーのデザインをカスタマイズする一例として、色や形を変更する方法があります。

下記のサンプルコードでは、C++を用いてプログレスバーの背景色と進行色をカスタマイズする方法を表しています。

#include <iostream>
#include <windows.h>  // Windowsプラットフォーム用

// プログレスバーの描画関数
void drawProgressBar(int width, int percent, const char* color) {
    std::cout << color; // 色の適用
    std::cout << "[";
    int pos = (width * percent) / 100;
    for (int i = 0; i < width; ++i) {
        if (i < pos) std::cout << "=";
        else std::cout << " ";
    }
    std::cout << "] " << percent << " %\r";
    std::cout.flush();
}

int main() {
    const char* RED = "\x1b[31m";
    const char* RESET = "\x1b[0m";
    for (int i = 0; i <= 100; ++i) {
        drawProgressBar(50, i, RED);
        Sleep(100);  // 進捗更新のための遅延
    }
    std::cout << RESET; // 色のリセット
    return 0;
}

このコードは、プログレスバーの進行状況を赤色で表示するものです。

関数 drawProgressBar は、幅(width)、進捗状況(percent)、色(color)をパラメータとして受け取り、指定された色でプログレスバーを描画します。

main 関数では、プログレスバーの進行状況を0から100まで1ずつ増やしていき、その都度 drawProgressBar 関数を呼び出しています。

○サンプルコード4:異なる色とスタイルを適用する

プログレスバーに異なる色やスタイルを適用することで、よりユーザーフレンドリーなインターフェースを実現できます。

例えば、進捗状況に応じて色が変化するプログレスバーを作成することが可能です。

下記のサンプルコードは、進行状況に応じて色が変わるプログレスバーを表しています。

#include <iostream>
#include <windows.h>

// 色を変更する関数
const char* changeColor(int percent) {
    if (percent < 33) return "\x1b[31m"; // 赤色
    else if (percent < 66) return "\x1b[33m"; // 黄色
    return "\x1b[32m"; // 緑色
}

void drawProgressBar(int width, int percent) {
    const char* color = changeColor(percent);
    std::cout << color;
    std::cout << "[";
    int pos = (width * percent) / 100;
    for (int i = 0; i < width; ++i) {
        if (i < pos) std::cout << "=";
        else std::cout << " ";
    }
    std::cout << "] " << percent << " %\r";
    std::cout.flush();
}

int main() {
    for (int i = 0; i <= 100; ++i) {
        drawProgressBar(50, i);
        Sleep(100);
    }
    std::cout << "\x1b[0m"; // 色のリセット
    return 0;
}

このコードでは、changeColor 関数を用いて進捗状況に応じて色を変更しています。

プログレスバーが進むにつれて赤から黄色、最終的に緑色に変化していきます。

こうした動的な要素は、ユーザーの注意を引きやすく、プロセスの進行状況を直感的に理解させる効果があります。

●C++でプログレスバーを応用する方法

C++でのプログレスバーの応用は、多様なシナリオに適応できる柔軟性を持っています。

ユーザーインタラクションに応じて変化するプログレスバーや、マルチスレッド環境での進行状況の管理など、応用範囲は広いです。

これらの応用は、プログラムのユーザビリティを向上させるだけでなく、処理の進行状況をより正確に反映するために重要です。

○サンプルコード5:マルチスレッド環境でのプログレスバー

マルチスレッド環境では、異なるスレッドが同時に動作しながら進行状況を更新する必要があります。

下記のサンプルコードは、マルチスレッドを使用してプログレスバーを制御する方法を表しています。

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> progress(0);

void worker() {
    for (int i = 0; i < 100; ++i) {
        progress++;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void drawProgressBar(int width) {
    while (progress < 100) {
        int pos = (width * progress) / 100;
        std::cout << "[";
        for (int i = 0; i < width; ++i) {
            if (i < pos) std::cout << "=";
            else std::cout << " ";
        }
        std::cout << "] " << progress << " %\r";
        std::cout.flush();
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

int main() {
    std::thread workerThread(worker);
    drawProgressBar(50);
    workerThread.join();
    return 0;
}

このコードでは、std::atomic<int>を用いてプログレスの値を安全に更新しています。

worker関数は別スレッドで実行され、進行状況を更新します。一方、drawProgressBar関数はプログレスバーを画面に表示し続けます。

これにより、マルチスレッド環境でもプログレスバーの表示が正確に行われます。

○サンプルコード6:ユーザーインタラクションに応じたプログレスバー

ユーザーのインタラクションに基づいてプログレスバーを更新することも可能です。

例えば、ユーザーがボタンをクリックする度にプログレスバーの進行状況を更新することができます。

下記のコードは、ユーザーの操作に応じてプログレスバーを更新する簡単な例を表しています。

#include <iostream>
#include <conio.h>  // _kbhit() と _getch() のため

int main() {
    int progress = 0;
    std::cout << "Press any key to advance the progress bar.\n";

    while (progress < 100) {
        if (_kbhit()) {
            progress += 10;  // キーが押されると10%進行
            _getch();  // キー入力を取得(無視)
            std::cout << "[";
            for (int i = 0; i < 50; ++i) {
                if (i < (progress / 2)) std::cout << "=";
                else std::cout << " ";
            }
            std::cout << "] " << progress << " %\r";
            std::cout.flush();
        }
    }

    return 0;
}

このプログラムでは、ユーザーがキーボードを押すたびに、プログレスバーが10%ずつ進みます。

_kbhit()関数はキーボードの入力を検出し、_getch()関数はその入力を取得します。

これにより、プログレスバーはユーザーの操作に反応して進行します。

●注意点と対処法

C++でプログレスバーを実装する際には、いくつかの注意点があります。

これらを理解し、適切に対処することで、プログレスバーの効果的な利用が可能となります。

特に重要なのは、メモリ管理とパフォーマンスの最適化です。

○メモリ管理の重要性

C++では、メモリ管理が重要な要素となります。

特に、プログレスバーのような動的に更新される要素では、メモリリークを避けるために注意が必要です。

例えば、動的に割り当てたメモリは、使用後に適切に解放する必要があります。

プログレスバーを表示するために新しいウィンドウやウィジェットを作成する際には、これが特に重要になります。

プログレスバーの実装におけるメモリリークを防ぐための一般的なアプローチは、スマートポインタの使用です。

スマートポインタは、オブジェクトのライフサイクルを自動的に管理し、不要になったメモリを適切に解放します。

ここでは、スマートポインタを使用したプログレスバーの簡単な例を紹介します。

#include <iostream>
#include <memory>

class ProgressBar {
public:
    void update(int value) {
        // プログレスバーの更新処理
        std::cout << "Progress: " << value << "%" << std::endl;
    }
};

int main() {
    std::unique_ptr<ProgressBar> progressBar(new ProgressBar());
    for (int i = 0; i <= 100; i += 10) {
        progressBar->update(i);
        // 何らかの処理
    }
    return 0;
}

このコードでは、std::unique_ptrを使用してProgressBarオブジェクトを管理しています。

これにより、ProgressBarオブジェクトは自動的に適切なタイミングで解放されます。

○パフォーマンスの最適化

パフォーマンスの最適化も、プログレスバーの実装において重要です。

プログレスバーの更新処理が重い場合、アプリケーションのレスポンスが悪化する可能性があります。

したがって、プログレスバーの描画処理は効率的に行う必要があります。

例えば、プログレスバーの更新頻度を制限することで、不必要な再描画を避けることができます。

また、プログレスバーの描画処理が他の処理に影響を与えないように、別のスレッドで実行することも一つの方法です。

下記の例では、プログレスバーの更新処理を別のスレッドで行うことで、アプリケーションのパフォーマンスを向上させる方法を表しています。

#include <iostream>
#include <thread>
#include <chrono>

void updateProgressBar(int &progress) {
    while (progress < 100) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        progress += 10;
        std::cout << "Progress: " << progress << "%" << std::endl;
    }
}

int main() {
    int progress = 0;
    std::thread progressThread(updateProgressBar, std::ref(progress));

    // ここで他の重要な処理を実行する

    progressThread.join();  // スレッドの完了を待つ
    return 0;
}

このコードでは、updateProgressBar関数を別スレッドで実行し、メインスレッドは他の処理に集中できるようにしています。

これにより、プログレスバーの更新とメイン処理が同時に進行し、アプリケーションの応答性を維持することができます。

まとめ

この記事では、C++でプログレスバーを実装するための多様な方法と、その応用例を詳細に解説しました。

基本的なプログレスバーの表示からカスタマイズ、応用技術に至るまで、様々なシナリオで活用できる知識を紹介しました。

また、メモリ管理とパフォーマンス最適化の重要性にも触れ、効率的でユーザーフレンドリーなプログレスバーの実装方法を紹介してきました。

この知識を活用することで、C++におけるプログレスバーの実装が、より効果的かつ効率的に行えるでしょう。