Qtにおけるダイアログボックスの基本と種類

一、ダイアログの概念

ダイアログとは、ユーザーとの短いやり取りを行うトップレベルウィンドウです。Qtにおけるすべてのダイアログウィンドウの基底クラスはQDialogです。QDialogはQWidgetを継承しており、コンテナ型のコンポーネントです。

二、QDialogの意味

QDialogは、専用の対話ウィンドウとして存在します。QDialogは、他のコンテナに子部品として埋め込むことはできません。QDialogは、ウィンドウスタイルがカスタマイズされた特殊なQWidgetです。

#include <QApplication>
#include <QWidget>
#include <QDialog>

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

    // QWidgetを親としてQDialogを作成し、表示する
    QWidget mainWindow;
    QDialog dialog(&mainWindow);
    dialog.show();

    return app.exec();
}

三、ダイアログの種類

1. モーダルダイアログ(QDialog::exec())

表示後、親ウィンドウとのインタラクションができません。ブロッキング式のダイアログ呼び出し方法です。

2. 非モーダルダイアログ(QDialog::show())

表示後、独立して存在し、親ウィンドウとのインタラクションが可能です。ノンブロッキング式の呼び出し方法です。

3. 一般的な使用場面

モーダルダイアログは、ユーザーの選択に依存する必要がある場面(80%)で使用されます。例:メッセージ表示、テキスト選択、印刷設定など。

非モーダルダイアログは、特殊な機能設定の場面(20%)で使用されます。例:検索操作、プロパティ設定など。

4. 小技

スタック上でモーダルダイアログを作成するのが最もシンプルで一般的です。非モーダルダイアログは通常、ヒープ上で作成する必要があります。QDialog::setModal関数を使用して、混合特性のダイアログを作成できます。非モーダルダイアログにはQt::WA_DeleteOnClose属性を指定する必要があります。

// DialogExample.h
#ifndef DIALOGEXAMPLE_H
#define DIALOGEXAMPLE_H

#include <QDialog>
#include <QPushButton>

class DialogExample : public QDialog
{
    Q_OBJECT
protected:
    QPushButton modalButton;
    QPushButton nonModalButton;
    QPushButton mixedButton;
protected slots:
    void onModalButtonClicked();
    void onNonModalButtonClicked();
    void onMixedButtonClicked();
public:
    DialogExample(QWidget *parent = nullptr);
    ~DialogExample();
};

#endif // DIALOGEXAMPLE_H
// DialogExample.cpp
#include "DialogExample.h"
#include <QDebug>

DialogExample::DialogExample(QWidget *parent)
    : QDialog(parent), modalButton(this), nonModalButton(this), mixedButton(this)
{
    modalButton.setText("モーダル");
    modalButton.move(35, 20);
    modalButton.resize(100,30);

    nonModalButton.setText("非モーダル");
    nonModalButton.move(35, 60);
    nonModalButton.resize(100,30);

    mixedButton.setText("混合");
    mixedButton.move(35, 100);
    mixedButton.resize(100,30);

    connect(&modalButton, SIGNAL(clicked()), this, SLOT(onModalButtonClicked()));
    connect(&nonModalButton, SIGNAL(clicked()), this, SLOT(onNonModalButtonClicked()));
    connect(&mixedButton, SIGNAL(clicked()), this, SLOT(onMixedButtonClicked()));

    resize(170,170);
}

void DialogExample::onModalButtonClicked()
{
    qDebug() << "モーダルボタンがクリックされました(開始)";

    QDialog modalDialog(this); // スタック上で生成
    modalDialog.exec(); // exec()を呼び出してモーダルダイアログにする。ブロッキング式。

    qDebug() << "モーダルボタンがクリックされました(終了)";
}
void DialogExample::onNonModalButtonClicked()
{
    qDebug() << "非モーダルボタンがクリックされました(開始)";

    QDialog* nonModalDialog = new QDialog(this); // ヒープ上で割り当て、親ウィンドウを指定すると常に親ウィンドウの最上位に表示される
    nonModalDialog->setAttribute(Qt::WA_DeleteOnClose);
    nonModalDialog->show(); // 非モーダルダイアログはノンブロッキング式なので、生成後にすぐに下の処理に進む。そのためヒープ上で生成する必要がある

    qDebug() << "非モーダルボタンがクリックされました(終了)";
}
void DialogExample::onMixedButtonClicked()
{
    qDebug() << "混合ボタンがクリックされました(開始)";

    QDialog* mixedDialog = new QDialog(this);
    mixedDialog->setAttribute(Qt::WA_DeleteOnClose);
    mixedDialog->setModal(true); // 混合ダイアログを設定。bool型のパラメータに注意
    mixedDialog->show();

    qDebug() << "混合ボタンがクリックされました(終了)";
}

DialogExample::~DialogExample()
{
}

四、ダイアログの戻り値

モーダルダイアログのみ戻り値の概念を持っています。モーダルダイアログの戻り値は、対話結果を示すために使用されます。QDialog::exec()の戻り値が対話結果です。

  • void QDialog::done(int i): ダイアログを閉じ、引数を対話結果として返します。
  • QDialog::Accepted: ユーザーの操作が成功したことを示します。
  • QDialog::Rejected: ユーザーの操作が失敗したことを示します。
// ReturnDialogExample.h
#ifndef RETURNDIALOGEXAMPLE_H
#define RETURNDIALOGEXAMPLE_H

#include <QDialog>
#include <QPushButton>

class ReturnDialogExample : public QDialog
{
    Q_OBJECT
protected:
    QPushButton acceptButton;
    QPushButton rejectButton;
    QPushButton customButton;
protected slots:
    void onAcceptButtonClicked();
    void onRejectButtonClicked();
    void onCustomButtonClicked();
public:
    ReturnDialogExample(QWidget *parent = nullptr);
    ~ReturnDialogExample();
};

#endif // RETURNDIALOGEXAMPLE_H
// ReturnDialogExample.cpp
#include "ReturnDialogExample.h"
#include <QDebug>

ReturnDialogExample::ReturnDialogExample(QWidget *parent)
    : QDialog(parent), acceptButton(this), rejectButton(this), customButton(this)
{
    acceptButton.setText("成功");
    acceptButton.move(35, 20);
    acceptButton.resize(100,30);

    rejectButton.setText("失敗");
    rejectButton.move(35, 60);
    rejectButton.resize(100,30);

    customButton.setText("カスタム");
    customButton.move(35, 100);
    customButton.resize(100,30);

    connect(&acceptButton, SIGNAL(clicked()), this, SLOT(onAcceptButtonClicked()));
    connect(&rejectButton, SIGNAL(clicked()), this, SLOT(onRejectButtonClicked()));
    connect(&customButton, SIGNAL(clicked()), this, SLOT(onCustomButtonClicked()));

    resize(170,170);
}

void ReturnDialogExample::onAcceptButtonClicked()
{
    qDebug() << "成功ボタンがクリックされました";
    done(42); // 任意の成功コードを返す
}
void ReturnDialogExample::onRejectButtonClicked()
{
    qDebug() << "失敗ボタンがクリックされました";
    done(99); // 任意の失敗コードを返す
}
void ReturnDialogExample::onCustomButtonClicked()
{
    qDebug() << "カスタムボタンがクリックされました";
    done(0); // 任意のカスタムコードを返す
}

ReturnDialogExample::~ReturnDialogExample()
{
}
// main.cpp
#include <QApplication>
#include "ReturnDialogExample.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ReturnDialogExample dialog;
    int result = dialog.exec(); // メッセージループに入るので、戻り値はここで取得

    switch (result) {
    case 42:
        qDebug() << "操作は成功しました";
        break;
    case 99:
        qDebug() << "操作は失敗しました";
        break;
    default:
        qDebug() << "カスタムコード: " << result;
        break;
    }
    return result;
}

五、まとめ

  • ダイアログにはモーダルと非モーダルの2種類がある。
  • モーダルダイアログはブロッキング方式である。
  • モーダルダイアログはユーザーの操作結果に依存する場面で使用する。
  • 非モーダルダイアログはノンブロッキング方式である。
  • 非モーダルダイアログは機能設定の場面で使用する。

タグ: Qt QDialog C++ modal dialog non-modal dialog

8月6日 08:35 投稿