【初心者向け】Qt Widgetsでプログレスバーを駆使する!QProgressDialog::setBar()の解説


使い方

QProgressDialog *progressDialog = new QProgressDialog(this);
progressDialog->setLabelText("処理中...");
progressDialog->setMinimum(0);
progressDialog->setMaximum(100);

QProgressBar *progressBar = new QProgressBar();
progressDialog->setBar(progressBar);

progressDialog->show();

// 処理を実行
for (int i = 0; i < 100; ++i) {
    progressDialog->setValue(i);
    // 処理を実行
}

progressDialog->close();

説明

  • close() 関数を使用して、ダイアログウィジェットを閉じます。
  • 処理を実行します。
  • setValue() 関数を使用して、プログレスバーの現在の値を設定します。
  • show() 関数を使用して、ダイアログウィジェットを表示します。
  • setBar() 関数を使用して、QProgressBar オブジェクトをダイアログウィジェットに設定します。
  • QProgressBar オブジェクトを作成します。
  • setMinimum() 関数と setMaximum() 関数を使用して、プログレスバーの最小値と最大値を設定します。
  • setLabelText() 関数を使用して、ダイアログウィジェットに表示されるラベルテキストを設定します。
  • QProgressDialog オブジェクトを作成します。
  • QProgressBar は、プログレスバーのスタイルや外観をカスタマイズするために使用できます。
  • QProgressDialog には、setCancelButtonText() 関数を使用してキャンセルボタンのテキストを設定したり、autoClose() 関数を使用して処理完了時に自動的に閉じるかどうかを設定したりするなどの他の関数も用意されています。

以下の例では、QProgressDialog を使用して、ファイルのコピーの進行状況を表示する方法を示します。

QProgressDialog *progressDialog = new QProgressDialog(this);
progressDialog->setLabelText("ファイルをコピーしています...");
progressDialog->setMinimum(0);
progressDialog->setMaximum(100);

QProgressBar *progressBar = new QProgressBar();
progressDialog->setBar(progressBar);

progressDialog->show();

// ファイルをコピーする
QFile sourceFile("source.txt");
QFile targetFile("target.txt");

if (sourceFile.open(QIODevice::ReadOnly)) {
    if (targetFile.open(QIODevice::WriteOnly)) {
        qint64 size = sourceFile.size();
        qint64 bytesCopied = 0;

        while (bytesCopied < size) {
            qint64 bytesRead = sourceFile.read(buffer, sizeof(buffer));
            if (bytesRead < 0) {
                break;
            }

            targetFile.write(buffer, bytesRead);
            bytesCopied += bytesRead;

            progressDialog->setValue((int)(100 * bytesCopied / size));
        }

        targetFile.close();
    }

    sourceFile.close();
}

progressDialog->close();


ファイルのコピー

#include <QApplication>
#include <QProgressDialog>
#include <QFile>

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

    QProgressDialog *progressDialog = new QProgressDialog;
    progressDialog->setLabelText("ファイルをコピーしています...");
    progressDialog->setMinimum(0);
    progressDialog->setMaximum(100);

    QProgressBar *progressBar = new QProgressBar;
    progressDialog->setBar(progressBar);

    progressDialog->show();

    // ファイルをコピーする
    QFile sourceFile("source.txt");
    QFile targetFile("target.txt");

    if (sourceFile.open(QIODevice::ReadOnly)) {
        if (targetFile.open(QIODevice::WriteOnly)) {
            qint64 size = sourceFile.size();
            qint64 bytesCopied = 0;

            while (bytesCopied < size) {
                qint64 bytesRead = sourceFile.read(buffer, sizeof(buffer));
                if (bytesRead < 0) {
                    break;
                }

                targetFile.write(buffer, bytesRead);
                bytesCopied += bytesRead;

                progressDialog->setValue((int)(100 * bytesCopied / size));
            }

            targetFile.close();
        }

        sourceFile.close();
    }

    progressDialog->close();

    return app.exec();
}

長時間実行タスクの進行状況表示

以下の例は、QProgressDialog を使用して、長時間実行タスクの進行状況を表示する方法を示しています。

#include <QApplication>
#include <QProgressDialog>
#include <QThread>

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

    QProgressDialog *progressDialog = new QProgressDialog;
    progressDialog->setLabelText("長い処理を実行しています...");
    progressDialog->setMinimum(0);
    progressDialog->setMaximum(100);

    QProgressBar *progressBar = new QProgressBar;
    progressDialog->setBar(progressBar);

    progressDialog->show();

    // 長時間実行タスクを別スレッドで実行する
    QThread *thread = new QThread;
    MyLongRunningTask *task = new MyLongRunningTask;
    task->moveToThread(thread);

    connect(task, &MyLongRunningTask::progressChanged, progressDialog, &QProgressDialog::setValue);
    connect(thread, &QThread::finished, task, &QObject::deleteLater);
    connect(thread, &QThread::finished, progressDialog, &QProgressDialog::close);

    thread->start();

    return app.exec();
}

以下の例は、QProgressDialog を使用して、処理中にキャンセルボタンを表示する方法を示しています。

#include <QApplication>
#include <QProgressDialog>
#include <QThread>

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

    QProgressDialog *progressDialog = new QProgressDialog;
    progressDialog->setLabelText("長い処理を実行しています...");
    progressDialog->setMinimum(0);
    progressDialog->setMaximum(100);
    progressDialog->setCancelButton(QProgressDialog::Cancel);

    QProgressBar *progressBar = new QProgressBar;
    progressDialog->setBar(progressBar);

    progressDialog->show();

    // 長時間実行タスクを別スレッドで実行する
    QThread *thread = new QThread;
    MyLongRunningTask *task = new MyLongRunningTask;
    task->moveToThread(thread);

    connect(task, &MyLongRunningTask::progressChanged, progressDialog, &QProgressDialog::setValue);
    connect(progressDialog, &QProgressDialog::cancelClicked, task, &MyLongRunningTask::cancel);
    connect(thread, &QThread::finished, task, &QObject::deleteLater);
    connect(thread, &QThread::finished, progressDialog, &QProgressDialog::close);

    thread->start();

    return app.exec();
}
  • QProgressDialog には、他にも多くの機能があります。詳細については、Qt ドキュメントを参照してください。
  • これらの例はあくまで基本的なものです。ご自身のニーズに合わせてカスタマイズする必要があります。


代替方法

  • ステータスラベルを使用する
    プログレスバーを使用せずに、ステータスラベルを使用して処理の進行状況をユーザーに伝えることもできます。この方法では、シンプルな方法で進行状況を表示できますが、プログレスバーほど視覚的に分かりやすいわけではありません。
  • カスタムウィジェットを使用する
    ダイアログウィジェット内に独自のプログレスバーウィジェットを作成して配置することができます。この方法では、プログレスバーの外観と動作をより細かく制御できます。

代替方法を選択する際の考慮事項

  • ユーザーエクスペリエンス
    プログレスバーは、ユーザーに処理の進行状況を視覚的に分かりやすく伝えるのに役立ちます。ステータスラベルを使用するよりも、ユーザーエクスペリエンスが向上する可能性があります。
  • コードの複雑さ
    カスタムウィジェットを使用する方法は、コードが最も複雑になります。QProgressBar を直接使用する方法は、最もシンプルです。
  • 必要な機能
    使用する方法は、必要な機能によって異なります。プログレスバーの外観と動作を細かく制御する必要がある場合は、カスタムウィジェットを使用する必要があります。シンプルな方法で進行状況を表示するだけであれば、ステータスラベルを使用するだけで十分な場合があります。

カスタムウィジェットを使用する

以下の例は、カスタムウィジェットを使用して QProgressDialog ダイアログウィジェット内にプログレスバーを追加する方法を示しています。

#include <QApplication>
#include <QProgressDialog>
#include <QWidget>
#include <QProgressBar>

class MyProgressDialog : public QProgressDialog
{
public:
    MyProgressDialog(QWidget *parent = nullptr);

protected:
    void showEvent(QShowEvent *event) override;
};

MyProgressDialog::MyProgressDialog(QWidget *parent) : QProgressDialog(parent)
{
    setLabelText("処理中...");
    setMinimum(0);
    setMaximum(100);
}

void MyProgressDialog::showEvent(QShowEvent *event)
{
    // カスタムウィジェットを作成して配置する
    QWidget *customWidget = new QWidget(this);
    customWidget->setLayout(new QHBoxLayout);

    QProgressBar *progressBar = new QProgressBar;
    customWidget->layout()->addWidget(progressBar);

    connect(this, &QProgressDialog::valueChanged, progressBar, &QProgressBar::setValue);

    customWidget->resize(QSize(200, 100));
    customWidget->move((width() - customWidget->width()) / 2, (height() - customWidget->height()) / 2);

    event->accept();
}

QProgressBar を直接使用する

以下の例は、QProgressDialog を使用せずに QProgressBar を直接ウィジェットに追加する方法を示しています。

#include <QApplication>
#include <QWidget>
#include <QProgressBar>

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

    QWidget *widget = new QWidget;
    widget->setWindowTitle("処理中...");

    QProgressBar *progressBar = new QProgressBar;
    progressBar->setMinimum(0);
    progressBar->setMaximum(100);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(progressBar);

    widget->setLayout(layout);
    widget->show();

    // 処理を実行する
    for (int i = 0; i < 100; ++i) {
        progressBar->setValue(i);
        // 処理を実行
    }

    return app.exec();
}

ステータスラベルを使用する

以下の例は、ステータスラベルを使用して処理の進行状況をユーザーに伝える方法を示しています。

#include <QApplication>
#include <QWidget>
#include <QLabel>

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

    QWidget *widget = new QWidget;
    widget->setWindowTitle("処理中...");

    QLabel *statusLabel = new QLabel;
    statusLabel->setText("処理中...");

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(statusLabel);