「Qtの基礎 - ダイアログ」の版間の差分
編集の要約なし  | 
				|||
| (同じ利用者による、間の11版が非表示) | |||
| 174行目: | 174行目: | ||
  <syntaxhighlight lang="c++">  |   <syntaxhighlight lang="c++">  | ||
  QString DirName = QFileDialog::getExistingDirectory();  |   QString DirName = QFileDialog::getExistingDirectory();  | ||
 </syntaxhighlight>  | |||
<br><br>  | |||
== 色選択ダイアログ(QColorDialogクラス) ==  | |||
RGBを10進または16進で入力できる色選択ダイアログである。<br>  | |||
<br>  | |||
<code>getColor</code>メソッドを使用すると、Qt標準の色選択ダイアログを表示する。<br>  | |||
 [書式] getColor(色, 親ウインドウのポインタ, ダイアログのタイトル, オプション)  | |||
<br>  | |||
以下の例では、初期表示として、青で透明度を指定している。<br>  | |||
<br>  | |||
<code>getColor</code>メソッドの戻り値は、選択した色情報クラスである。(キャンセルした場合、Validがfalseになる)<br>  | |||
色は、#AARRGGBB形式、#RRGGBB形式、Qt定義色(<code>Qt::red</code>等)で指定する。<br>  | |||
透明度(AA、アルファチャンネル)を省略する時、初期値は255となる。<br>  | |||
<code>ShowAlphaChannel</code>オプションを指定しない場合、AAに初期値を指定しても戻り値は固定でFF(255)となる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QColor color = QColorDialog::getColor("#800a64c8", this, tr("色選択"), QColorDialog::ShowAlphaChannel);  | |||
 if(color.isValid())  | |||
 {  | |||
    // color.name();  → "#0a64c8" (#RRGGBB)  | |||
    // color.name(QColor::HexArgb);  → "#800a64c8" (#AARRGGBB)  | |||
    // int r, g, b, a;  | |||
    // color.getRgb(&r, &g, &b, &a);  → r=10, g=100, b=200, a=128  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
<center>  | |||
QColorDialogのオプション(enum QColorDialog::ColorDialogOption)<br>  | |||
{| class="wikitable" style="background-color:#fefefe;"  | |||
|-  | |||
! style="background-color:#00ffff;" | オプション名   | |||
! style="background-color:#00ffff;" | 値   | |||
! style="background-color:#00ffff;" | 説明  | |||
|-  | |||
| ShowAlphaChannel || 0x00000001 || アルファチャンネル(透明度)を表示する。  | |||
|-  | |||
| NoButtons || 0x00000002 || OKとキャンセルのボタンを表示しない。<br>(ライブダイアログで役立つ)  | |||
|-  | |||
| DontUseNativeDialog || 0x00000004 || OS標準ではなくQt標準の色選択を使用する。<br>(指定しない場合、有効)。  | |||
|}  | |||
</center>  | |||
<br>  | |||
<code>getColor</code>メソッドの引数を全て省略する時、標準のダイアログが表示される。<br>  | |||
この時、標準ダイアログのタイトルは"Select Color"、色は白(#ffffff)、アルファチャンネルの項目は無い。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QColor color = QColorDialog::getColor();  | |||
 </syntaxhighlight>  | |||
<br><br>  | |||
== フォント選択ダイアログ(QFontDialog) ==  | |||
フォント選択ダイアログは、フォントを選択できるダイアログである。<br>  | |||
<code>QFontDialog</code>クラスの<code>getFont</code>メソッドは、Qt標準のフォント選択ダイアログを表示する。<br>  | |||
 [書式1] getFont(結果, 初期フォント, 親ウインドウのポインタ, ダイアログのタイトル, オプション)  | |||
 [書式2] getFont(結果, 親ウインドウのポインタ)  | |||
<br>  | |||
以下の例では、初期フォントを18pxのCourier、等幅フォントとしている。<br>  | |||
<code>getFont</code>メソッドの戻り値は、選択したフォント情報のクラスである。(キャンセルした場合、第1引数はfalseとなる)<br>  | |||
[Esc]キーを押下する場合は、キャンセルしたものと見なされる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 bool ok;  | |||
 QFont font = QFontDialog::getFont(&ok, QFont("Courier", 18), this, tr("フォント選択"), QFontDialog::MonospacedFonts);  | |||
 if(ok)  | |||
 {  | |||
    // font.family();  → "Courier"  | |||
    // font.pointSize();  → 18  | |||
    // font.italic();  → false (true:Font styleがItalic)  | |||
    // font.bold();  → false (true:Font styleがBold)  | |||
    // font.weight();  → 50 (bold()=trueの時は75)  | |||
    // font.strikeOut();  → false (true:EffectsのstrikeOutオン)  | |||
    // font.underline();  → false (true:Effectsのunderlineオン)  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
<center>  | |||
QFontDialogクラスのオプション(enum QFontDialog::FontDialogOption)<br>  | |||
{| class="wikitable" style="background-color:#fefefe;"  | |||
|-  | |||
! style="background-color:#00ffff;" | オプション名   | |||
! style="background-color:#00ffff;" | 値   | |||
! style="background-color:#00ffff;" | 説明  | |||
|-  | |||
| NoButtons || 0x00000001 || [OK]ボタンと[キャンセル]ボタンを表示しない。<br>(ライブダイアログで役立つ)<br><u>ただし、ダイアログ右上の[閉じる]ボタンが使用できなくなる。</u>  | |||
|-  | |||
| DontUseNativeDialog || 0x00000002 || OS標準ではなくQt標準のフォント選択を使用する。<br>指定しない場合、Qt標準のフォント選択を使用する。  | |||
|-  | |||
| ScalableFonts || 0x00000004 || スケーラブルフォントを表示する。<br>スケーラブルフォントとは、拡大縮小しても精度の変わらないフォントである。  | |||
|-  | |||
| NonScalableFonts || 0x00000008 || スケーラブルフォント以外を表示する。  | |||
|-  | |||
| MonospacedFonts || 0x00000010 || 等幅フォントを表示する。  | |||
|-  | |||
| ProportionalFonts || 0x00000020 || 可変幅フォントを表示する。  | |||
|}  | |||
</center>  | |||
<br>  | |||
第1引数は必須であり、他の引数を全て省略する時、標準のフォント選択ダイアログが表示される。<br>  | |||
この時、ダイアログのタイトルは"Select Font"、使用可能なフォントをアルファベット順に並べて、その先頭が選択された状態となる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 bool ok;  | |||
 QFont font = QFontDialog::getFont(&ok);  | |||
 </syntaxhighlight>  | |||
<br><br>  | |||
== インプットダイアログ ==  | |||
<br><br>  | |||
== 印刷ダイアログ ==  | |||
==== QPrintDialogクラス ====  | |||
印刷ダイアログにおいて、使用する場合は以下のヘッダファイルをインクルードする必要がある。<br>  | |||
 #include <QtPrintSupport>  | |||
<br>  | |||
また、プロジェクトファイル(.proファイル)に、以下のモジュールを追記する必要がある。<br>  | |||
 QT += core gui printsupport  | |||
<br>  | |||
下表に示すように、印刷ダイアログには、様々な支援クラスがある。<br>  | |||
<br>  | |||
印刷ダイアログを使用する場合は、描画デバイスが必要である。<br>  | |||
ページ設定等は、印刷ダイアログに組み込まれている。<br>  | |||
<center>  | |||
印刷関連クラス<br>  | |||
{| class="wikitable" style="background-color:#fefefe;"  | |||
|-  | |||
! style="background-color:#00ffff;" | クラス名   | |||
! style="background-color:#00ffff;" | 説明  | |||
|-  | |||
| QAbstractPrintDialog || 印刷ダイアログの抽象クラス  | |||
|-  | |||
| QPageSetupDialog || ページ設定  | |||
|-  | |||
| QPrintDialog || 印刷ダイアログ  | |||
|-  | |||
| QPrintEngine || 印刷サブシステムとのインターフェース定義  | |||
|-  | |||
| QPrintPreviewDialog || 印刷出力レイアウトのプレビューダイアログ  | |||
|-  | |||
| QPrintPreviewWidget || 印刷プレビューウィジェット  | |||
|-  | |||
| QPrinter || プリンタに出力する描画デバイス  | |||
|-  | |||
| QPrinterInfo || 既存プリンタの情報  | |||
|}  | |||
</center>  | |||
<br>  | |||
==== テキスト印刷 ====  | |||
文字の印刷は、QTextDocumentを使用すると簡単にできる。<br>  | |||
<br>  | |||
QTextEditクラス等は、QTextDocumentを取得できるので、テキストをセットする手間が省ける。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QPrinter printer(QPrinter::HighResolution);  | |||
 QPrintDialog dialog(&printer, this);  | |||
 if(dialog.exec() == QDialog::Accepted)  | |||
 {  | |||
    QTextDocument doc;  | |||
    doc.setPlainText("テキスト印刷のサンプルです。\n改行しました。");  | |||
    doc.print(&printer);  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== 画像印刷 ====  | |||
以下の例では、画像ファイル(image.jpgファイル)の縦横比を崩さずに、できるだけ大きなサイズで印刷している。<br>  | |||
# 印刷領域の横と縦から、縦横比を崩さずに画像が収まるサイズを求める。  | |||
# 求めたサイズで、印刷領域の横と縦を変更する。  | |||
# 描画領域を画像サイズにして画像を描けば、自動的にサイズ調整と印刷領域への転送が行われる。  | |||
:* <code>setViewport</code>メソッドを使用して、印刷領域のサイズを変更しない場合、縦横比が崩れる。  | |||
:* <code>setWindow</code>メソッドを使用して、描画領域のサイズを変更しない場合、小さな画像になる。  | |||
 <syntaxhighlight lang="c++">  | |||
 QPrinter printer(QPrinter::ScreenResolution);  | |||
 QPrintDialog dialog(&printer, this);  | |||
 if(dialog.exec() == QDialog::Accepted)  | |||
 {  | |||
    QPainter painter(&printer);  | |||
    QRect rect = painter.viewport();  | |||
    QPixmap pixmap("~/tmp/image.jpg");  | |||
    QSize size = pixmap.size();  | |||
    size.scale(rect.size(), Qt::KeepAspectRatio);  | |||
    painter.setViewport(rect.x(), rect.y(), size.width(), size.height());  | |||
    painter.setWindow(pixmap.rect());  | |||
    painter.drawPixmap(0, 0, pixmap);  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== ウィジェット印刷 ====  | |||
以下の例では、縦横比を崩さずに、横200pxでwidgetを印刷している。<br>  | |||
# <code>widget</code>クラスの<code>grab</code>メソッドを使用して、<code>QPixmap</code>クラスを生成する。(widgetの子要素も含まれる)  | |||
# 生成した<code>QPixmap</code>クラスの横を200pxにして描画する。縦は横に合わせて自動的に伸縮される。  | |||
 <syntaxhighlight lang="c++">  | |||
 QPrinter printer(QPrinter::ScreenResolution);  | |||
 QPrintDialog dialog(&printer, this);  | |||
 if(dialog.exec() == QDialog::Accepted)  | |||
 {  | |||
    QPixmap pixmap = widget->grab();  | |||
    QPainter painter(&printer);  | |||
    painter.drawPixmap(0, 0, pixmap.scaledToWidth(200));  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== 印刷プレビュー ====  | |||
以下の例では、用紙にA4縦を指定して印刷プレビューを表示している。<br>  | |||
実際の描画は、<code>redrawPreview</code>メソッド(ユーザ定義メソッド)で行う。<br>  | |||
<br>  | |||
用紙のサイズと向きは、プレビュー画面で設定できるため、省略可能である。<br>  | |||
プレビュー画面のサイズを指定しないと、とても小さな表示になるので注意すること。<br>  | |||
<br>  | |||
設定変更による描画要求シグナルには、<code>redrawPreview</code>メソッド(ユーザ定義メソッド)を接続する。<br>  | |||
<code>exec</code>メソッドを使用して、印刷プレビュー画面を表示する。(プレビュー画面を閉じるまで制御は戻らない)<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 // mainwindow.cpp  | |||
 QPrinter printer(QPrinter::HighResolution);  | |||
 printer.setPaperSize(QPrinter::A4);  | |||
 printer.setOrientation(QPrinter::Portrait);  | |||
 QPrintPreviewDialog preview(&printer, this);  | |||
 preview.setFixedSize(this->width() - 100, this->height());  | |||
 connect(&preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(redrawPreview(QPrinter*)));  | |||
 preview.exec();  | |||
 </syntaxhighlight>  | |||
<br>  | |||
描画関数<code>redrawPreview</code>メソッド(ユーザ定義メソッド)は、ヘッダファイルのスロットで宣言する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 // mainwindow.h  | |||
 private slots:  | |||
    void redrawPreview(QPrinter *printer);  | |||
 </syntaxhighlight>  | |||
<br>  | |||
以下の例では、メイン画面のハードコピーを印刷プレビューに表示している。<br>  | |||
用紙全体がプレビュー画面に収まるように、自動的に縮小表示される。<br>  | |||
[ページ設定]画面の用紙の向きを変更する場合、自動的に伸縮率が変化する。<br>  | |||
<br>  | |||
QPixmapクラスの生成以外は、画像印刷と同じ処理となる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 void MainWindow::redrawPreview(QPrinter *p)  | |||
 {  | |||
    QPainter painter(p);  | |||
    QRect rect = painter.viewport();  | |||
    QPixmap pixmap = this->grab();  | |||
    QSize size = pixmap.size();  | |||
    size.scale(rect.size(), Qt::KeepAspectRatio);  | |||
    painter.setViewport(rect.x(), rect.y(), size.width(), size.height());  | |||
    painter.setWindow(pixmap.rect());  | |||
    painter.drawPixmap(0, 0, pixmap);  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== 画像の印刷解像度(dpi)を設定する ====  | |||
画像ファイルで見かける解像度は、印刷解像度である。<br>  | |||
すなわち、dpiとは紙上1インチに表現する画素数の値のことである。<br>  | |||
<br>  | |||
例えば、1440[px] x 1440[px]、72[dpi]の画像を印刷する場合、紙上のサイズは、1440[px] / 72[dpi] = 20[inch] = 508[mm]となる。<br>  | |||
<br>  | |||
以下の例では、上記の値を<code>QImage</code>クラスに設定して保存している。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 // ドット / メートルに変換(72dpiの場合)  | |||
 int dpm = 72 / 0.0254;  | |||
 // 水平方向と垂直方向を別個に指定できる  | |||
 qimg.setDotsPerMeterX(dpm);  | |||
 qimg.setDotsPerMeterY(dpm);  | |||
 // dpiをファイル内に保持できるフォーマットのみ保存できる  | |||
 qimg.save(arrPath, "JPEG", -1);  | |||
 </syntaxhighlight>  | |||
<br><br>  | |||
== プログレスバーダイアログ ==  | |||
QProgressDialogクラスを使用して、標準で用意されているプログレスバーダイアログを表示する。<br>  | |||
<br>  | |||
QProgressDialogクラスの最後の引数はウインドウフラグであるが、ここでは使用しないため省略している。<br>  | |||
 [書式1] QProgressDialog <変数名>(親ウインドウのポインタ)  | |||
 [書式2] QProgressDialog <変数名>(表示文字列, キャンセルボタン文字列, 最小値, 最大値, 親ウインドウのポインタ)  | |||
<br>  | |||
以下の例では、プログレスバーにおいて、500[ms]ごとに10%ずつ増加させて表示している。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QProgressDialog ProgressDlg(tr("しばらくお待ちください・・・"), tr("キャンセル"), 0, 200, this);  | |||
 ProgressDlg.setWindowModality(Qt::WindowModal);  | |||
 ProgressDlg.setWindowTitle(tr("処理中"));  | |||
 ProgressDlg.show();  | |||
 for(int cnt = 0; cnt < 200; cnt += 20)  | |||
 {  | |||
    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);  | |||
    ProgressDlg.setValue(cnt);  | |||
    if(ProgressDlg.wasCanceled())  | |||
    {  | |||
       break;  | |||
    }  | |||
    Sleep(500);  | |||
 }  | |||
 progress.setValue(200);  | |||
 </syntaxhighlight>  | |||
<br>  | |||
また、全ての引数を省略する場合、標準のプログレスバーダイアログが表示される。<br>  | |||
表示文字列は無し、キャンセルボタンのラベル名は"Cancel"、プログレスバーの最小値は0、最大値は100となる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QProgressDialog progress;  | |||
  </syntaxhighlight>  |   </syntaxhighlight>  | ||
<br><br>  | <br><br>  | ||
| 231行目: | 541行目: | ||
     ModelessDlg->show();  |      ModelessDlg->show();  | ||
  }  |   }  | ||
 </syntaxhighlight>  | |||
<br>  | |||
モードレスダイアログ等を常に前面に表示する場合は、以下のように記述する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 ModelessDlg = std::make_unique<ModelessDialog>(this);  | |||
 ModelessDlg->setWindowFlags(Qt::WindowStaysOnTopHint);  | |||
 ModelessDlg->show();  | |||
 </syntaxhighlight>  | |||
<br><br>  | |||
== カスタムダイアログ ==  | |||
カスタムダイアログは、自由にレイアウト可能なダイアログである。<br>  | |||
QDialogクラスを使用して作成することができる。<br>  | |||
<br>  | |||
以下の例では、メール送信用のダイアログを作成している。(ただし、レイアウトと結果の取得のみ対応)<br>  | |||
<br>  | |||
[OK]ボタンを押下する時、<code>accepted</code>シグナルが発行されて、[CANCEL]ボタンを押下する時、<code>rejected</code>シグナルが発行される。<br>  | |||
各スロットは標準で用意されているため、任意の処理を記述せずに<code>1</code>または<code>0</code>を返す。<br>  | |||
また、サイズグリップは表示されないが、ウインドウのサイズは自由に変更できる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QFormLayout Form();  | |||
 Form.setLabelAlignment(Qt::AlignRight);  | |||
 Form.addRow(tr("送信先 :"), new QLineEdit);  | |||
 Form.addRow(tr("件名 :"), new QLineEdit);  | |||
 Form.addRow(tr("本文 :"), new QTextEdit);  | |||
 QDialogButtonBox BtnBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);  | |||
 BtnBox.button(QDialogButtonBox::Ok)->setText(tr("送信"));  | |||
 BtnBox.button(QDialogButtonBox::Cancel)->setText(tr("閉じる"));  | |||
 QVBoxLayout vbox;  | |||
 vbox.addLayout(Form);  | |||
 vbox.addWidget(BtnBox);  | |||
 QDialog Dlg(this);  | |||
 Dlg.setModal(true);  | |||
 Dlg.setWindowTitle(tr("メール送信"));  | |||
 Dlg.setLayout(vbox);  | |||
 connect(BtnBox, SIGNAL(accepted()), Dlg, SLOT(accept()));  | |||
 connect(BtnBox, SIGNAL(rejected()), Dlg, SLOT(reject()));  | |||
 // 1 : Ok(送信), 0 : Cancel(閉じる)  | |||
 int iRet = Dlg.exec();  | |||
 </syntaxhighlight>  | |||
<br>  | |||
以下の例では、6つの選択ボタンを表示している。<br>  | |||
<br>  | |||
各ボタンにはプロパティを設定してボタン番号を設定する。(buttonNoは任意の名前である)<br>  | |||
全てのボタンのイベントは、スロット<code>exitDialog</code>で処理する。<br>  | |||
<br>  | |||
最小サイズと最大サイズを同じ値に設定することで、ダイアログのサイズを固定している。<br>  | |||
サイズグリップをオフにしても、サイズ変更不可にはならない。<br>  | |||
<br>  | |||
ダイアログ右上の[x]ボタンを押下した場合、buttonは0になる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QStringList List;  | |||
 List << "グルメツアー" << "買い物ツアー" << "農業体験ツアー";  | |||
 List << "工場見学" << "寺社巡り" << "歴史に触れる旅";  | |||
 QLabel Label("コースを選択してください。");  | |||
 Label.setFixedHeight(30);  | |||
 QGridLayout Grid;  | |||
 Grid.setContentsMargins(20, 16, 20, 24); // left, top, right, bottom  | |||
 Grid.setHorizontalSpacing(20);  | |||
 Grid.setVerticalSpacing(0);  | |||
 for(int i = 0; i < 3; i++)  | |||
 {  | |||
    QLabel LabelCourse(QString((int)'A' + i) + " コース");  | |||
    LabelCourse.setFixedHeight(20);  | |||
    Grid.addWidget(LabelCourse, 0, i, Qt::AlignHCenter);  | |||
    QPushButton Btn(List[i]);  | |||
    Btn.setFixedSize(150, 40);  | |||
    Btn.setStyleSheet("background:green; color:lightyellow;");  | |||
    Btn.setProperty("buttonNo", i + 1);  | |||
    connect(&Btn, SIGNAL(clicked()), this, SLOT(exitDialog()));  | |||
    Grid.addWidget(&Btn, 1, i, Qt::AlignHCenter);  | |||
 }  | |||
 Grid.addWidget(new QLabel(""), 2, 0, 1, 3);  | |||
 for(int i = 0; i < 3; i++)  | |||
 {  | |||
    QLabel *label = new QLabel(QString((int)'D' + i) + " コース");  | |||
    label->setFixedHeight(20);  | |||
    Grid.addWidget(label, 3, i, Qt::AlignHCenter);  | |||
    QPushButton *pbtn = new QPushButton(list[i+3]);  | |||
    pbtn->setFixedSize(150, 40);  | |||
    pbtn->setStyleSheet("background:green; color:lightyellow;");  | |||
    pbtn->setProperty("buttonNo", i + 3 + 1);  | |||
    connect(pbtn, SIGNAL(clicked()), this, SLOT(exitDialog()));  | |||
    Grid.addWidget(pbtn, 4, i, Qt::AlignHCenter);  | |||
 }  | |||
 QWidget Widget;  | |||
 Widget.setLayout(&Grid);  | |||
 Widget.setStyleSheet("background:lightyellow;");  | |||
 QPushButton BtnQuit("どれも選ばない");  | |||
 BtnQuit.setProperty("buttonNo", 0);  | |||
 connect(&BtnQuit, SIGNAL(clicked()), this, SLOT(exitDialog()));  | |||
 QVBoxLayout vbox;  | |||
 vbox.addWidget(Label);  | |||
 vbox.addWidget(Widget);  | |||
 vbox.addStretch();  | |||
 vbox.addWidget(BtnQuit);  | |||
 QDialog Dlg(this);  | |||
 Dlg.setModal(true);  | |||
 Dlg.setWindowTitle(tr("ご案内"));  | |||
 Dlg.setSizeGripEnabled(false);  | |||
 Dlg.setMinimumSize(560, 290);  | |||
 Dlg.setMaximumSize(560, 290);  | |||
 Dlg.setLayout(vbox);  | |||
 // 0 : 選択しない, 1~6 : グルメ ~ 歴史に触れる  | |||
 int iRet = Dlg.exec();  | |||
 </syntaxhighlight>  | |||
<br>  | |||
mainwindow.hファイルにスロットの宣言を記述する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 // mainwindow.h  | |||
 private slots:  | |||
    void exitDialog();  | |||
 </syntaxhighlight>  | |||
<br>  | |||
スロットの処理を記述する。<br>  | |||
<br>  | |||
シグナルの送信元を調べて、QDialogであれば閉じる。<br>  | |||
送信元のウインドウがQDialogではない場合、処理は実行しない。<br>  | |||
buttonNoプロパティの値を取得して<code>done</code>メソッドを実行すると、ダイアログを閉じて<code>exec</code>メソッドの戻り値に変数iNoを渡す。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 // mainwindow.cpp  | |||
 void MainWindow::exitDialog()  | |||
 {  | |||
    QWidget *Window = static_cast<QWidget *>(sender())->window();  | |||
    if(win->inherits("QDialog"))  | |||
    {  | |||
       QDialog *Dlg = static_cast<QDialog *>(win);  | |||
       int iNo = (sender()->property("buttonNo")).toInt();  | |||
       Dlg->done(iNo);  | |||
    }  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br><br>  | |||
== メッセージボックス(QMessageBoxクラス) ==  | |||
QMessageBoxクラスを使用して、メッセージボックスを表示する。<br>  | |||
 [書式] QMessageBox <変数名>(親ウインドウのポインタ, タイトル, 表示文字列, ボタン, デフォルト)  | |||
<br>  | |||
<center>  | |||
QMessageBoxクラスのアイコン(enum QMessageBox::Icon)<br>  | |||
{| class="wikitable" style="background-color:#fefefe;"  | |||
|-   | |||
! style="background-color:#00ffff;" | アイコン   | |||
! style="background-color:#00ffff;" | 値   | |||
! style="background-color:#00ffff;" | 説明  | |||
! style="background-color:#00ffff;" | 標準Pixmap   | |||
|-  | |||
| NoIcon || 0 || アイコンなし ||   | |||
|-  | |||
| Information || 1 || 情報 || SP_MessageBoxInformation  | |||
|-  | |||
| Warning || 2 || 警告 || SP_MessageBoxWarning  | |||
|-  | |||
| Critical || 3 || 重大な問題 || SP_MessageBoxCritical  | |||
|-  | |||
| Question || 4 || 質問 || SP_MessageBoxQuestion  | |||
|}  | |||
</center>  | |||
<br>  | |||
==== 簡素なメッセージボックス ====  | |||
状況に応じて、以下に示す4種類を使い分ける。<br>  | |||
変数iRetには、<code>QMessageBox::Yes</code>または<code>QMessageBox::No</code>のいずれかが入る。<br>  | |||
また、<code>QMessageBox::question</code>は、ボタンを指定しない場合でも[Yes]ボタンと[No]ボタンが表示される。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QMessageBox::information(this, tr("情報"), tr("メッセージ"));  | |||
 QMessageBox::warning(this, tr("警告"), tr("メッセージ"));  | |||
 QMessageBox::critical(this, tr("致命的エラー"), tr("メッセージ"));  | |||
 int iRet = QMessageBox::question(this, tr("確認"), tr("メッセージ"));  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== 標準のメッセージボックス ====  | |||
複数のボタンを表示して選択されたボタンを返す。<br>  | |||
<br>  | |||
書式1は最初の3つの引数が必須、書式2は必要な情報を後で指定する。<br>  | |||
書式1の最後の引数にはウインドウフラグがあるが、ここでは省略している。<br>  | |||
 [書式1] QMessageBox <変数名>(アイコン, タイトル, 表示文字列, ボタン, 親ウインドウのポインタ)  | |||
 [書式2] QMessageBox <変数名>(親ウインドウのポインタ)  | |||
<br>  | |||
以下の例では、上記の書式1の形式でメッセージボックスを表示している。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QMessageBox MsgBox(QMessageBox::Question, tr("確認"), tr("これでよろしいですか?"),   | |||
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, this);  | |||
 int iRet = MsgBox.exec();  | |||
 </syntaxhighlight>  | |||
<br>  | |||
以下の例では、上記の書式2の形式でメッセージボックスを表示している。<br>  | |||
<code>setDefaultButton</code>メソッドにより、標準でフォーカスが当たるボタンを指定できる。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QMessageBox MsgBox(this);  | |||
 MsgBox.setIcon(QMessageBox::Question);  | |||
 MsgBox.setWindowTitle(tr("確認"));  | |||
 MsgBox.setText(tr("これでよろしいですか?"));  | |||
 MsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);  | |||
 MsgBox.setDefaultButton(QMessageBox::Cancel);  | |||
 MsgBox.setButtonText(QMessageBox::Yes, tr("OK"));  | |||
 MsgBox.setButtonText(QMessageBox::No, tr("Cancel"));  | |||
 MsgBox.setButtonText(QMessageBox::Cancel, tr("Back"));  | |||
 int iRet = MsgBox.exec();  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== ボタンについて ====  | |||
QMessageBoxクラスでは、様々なボタンが用意されている。<br>  | |||
各ボタンには意味があるため、それに応じて使用する必要がある。<br>  | |||
<br>  | |||
<u>ボタンは記述した順番で並ぶわけではないので注意すること。</u><br>  | |||
<u>[Cancel]ボタンを記述しない場合、メッセージボックス右上の[x]ボタンが使用できなくなる可能性がある。</u><br>  | |||
<center>  | |||
QMessageBoxクラスのボタン(enum QMessageBox::StandardButton)<br>  | |||
{| class="wikitable" style="background-color:#fefefe;"  | |||
|-  | |||
! style="background-color:#00ffff;" | ボタン名   | |||
! style="background-color:#00ffff;" | 値   | |||
! style="background-color:#00ffff;" | 説明   | |||
! style="background-color:#00ffff;" | 役割名  | |||
|-  | |||
| Ok || 0x00000400 || 了解 || AcceptRole  | |||
|-  | |||
| Open || 0x00002000 || 開く || AcceptRole  | |||
|-  | |||
| Save || 0x00000800 || 保存 || AcceptRole  | |||
|-  | |||
| Cancel || 0x00400000 || キャンセル || RejectRole  | |||
|-  | |||
| Close || 0x00200000 || 閉じる || RejectRole  | |||
|-  | |||
| Discard || 0x00800000 || 破棄または保存しない || DestructiveRole  | |||
|-  | |||
| Apply || 0x02000000 || 現在の変更を適用する || ApplyRole  | |||
|-  | |||
| Reset || 0x04000000 || リセット || ResetRole  | |||
|-  | |||
| RestoreDefaults || 0x08000000 || デフォルトに戻す || ResetRole  | |||
|-  | |||
| Help || 0x01000000 || ヘルプ || HelpRole  | |||
|-  | |||
| SaveAll || 0x00001000 || 全て保存 || AcceptRole  | |||
|-  | |||
| Yes || 0x00004000 || はい || YesRole  | |||
|-  | |||
| YesToAll || 0x00008000 || 全てはい || YesRole  | |||
|-  | |||
| No || 0x00010000 || いいえ || NoRole  | |||
|-  | |||
| NoToAll || 0x00020000 || 全ていいえ || NoRole  | |||
|-  | |||
| Abort || 0x00040000 || 異常終了 || RejectRole  | |||
|-  | |||
| Retry || 0x00080000 || 再試行 || AcceptRole  | |||
|-  | |||
| Ignore || 0x00100000 || 無視 || AcceptRole  | |||
|-  | |||
| NoButton || 0x00000000 || ボタンなし || 無効  | |||
|}		  | |||
</center>  | |||
<br>  | |||
下表に、各ボタンの役割を示す。<br>  | |||
<center>  | |||
QMessageBoxクラスのボタンの役割(enum QMessageBox::ButtonRole)<br>  | |||
{| class="wikitable" style="background-color:#fefefe;"  | |||
|-  | |||
! style="background-color:#00ffff;" | ロール名   | |||
! style="background-color:#00ffff;" | 値   | |||
! style="background-color:#00ffff;" | 説明  | |||
|-  | |||
| InvalidRole || -1 || 無効  | |||
|-  | |||
| AcceptRole || 0 || 同意および受諾<br>(OK, Save, SaveAll, Open, Retry, Ignore)  | |||
|-  | |||
| RejectRole || 1 || 拒否<br>(Abort, Close, Cancel)  | |||
|-  | |||
| DestructiveRole || 2 || 変更を破棄して閉じる。<br>(Discard)  | |||
|-  | |||
| ActionRole || 3 || ダイアログ内の要素を変更する。  | |||
|-  | |||
| HelpRole || 4 || ヘルプ要求<br>(Help)  | |||
|-  | |||
| YesRole || 5 || 受諾または全て受諾<br>(Yes, YesToAll)  | |||
|-  | |||
| NoRole || 6 || 拒否または全て拒否<br>(No, NoToAll)  | |||
|-  | |||
| ResetRole || 7 || ダイアログ内の項目をデフォルトに戻す。<br>(Reset, RestoreDefaults)  | |||
|-  | |||
| ApplyRole || 8 || 変更を適用する。<br>(Apply)  | |||
|}  | |||
</center>  | |||
<br>  | |||
==== プッシュボタン追加 ====  | |||
メッセージボックスに任意のボタンを追加する場合、以下のように記述する。<br>  | |||
任意のボタンでは、役割も指定する必要がある。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QMessageBox MsgBox(this);  | |||
 QPushButton *anyButton = MsgBox.addButton(tr("hoge"), QMessageBox::ActionRole);  | |||
 MsgBox.setWindowTitle(tr("hogeボタンの表示"));  | |||
 MsgBox.setText(tr("メッセージ"));  | |||
 MsgBox.exec();  | |||
 if(MsgBox.clickedButton() == anyButton)  | |||
 {  // [hoge]ボタンが押下された場合  | |||
    // 処理を記述  | |||
 }  | |||
 </syntaxhighlight>  | |||
<br>  | |||
==== 概要ダイアログ ====  | |||
Qtのライセンス等の情報を表示する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QMessageBox MsgBox;  | |||
 MsgBox.aboutQt(this, tr("Qtについて"));  | |||
 </syntaxhighlight>  | |||
<br>  | |||
以下の例では、ソフトウェアの説明を表示している。<br>  | |||
<code>about</code>メソッドでは、必ずソフトウェアのアイコンが表示される。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QString strOverView = "<span style=\"font-weight:bold\">Qtサンプル画面</span><br><br>"  | |||
                       "このプログラムはQt C++で作成したものです。<br>"  | |||
                       "いろいろなレイアウトやウィジェットの使用例が入っています。<br><br>"  | |||
                       "※ご注意<br>"  | |||
                       "必ずしもこの使用法が正しいとは限りません。<br>"  | |||
                       "自分で使うプログラムとしては十分動くというだけです。<br>"  | |||
                       "何の保証もありませんので、自己責任でお使いください。<br><br>"  | |||
                       "Top Page: "  | |||
                       "<a href=\"http://www.sample.com/index.html\">"  | |||
                       "http://dorafop.my.coocan.jp/index.html</a>";  | |||
 QMessageBox MsgBox;  | |||
 MsgBox.about(this, tr("このプログラムについて"), strOverView);  | |||
 </syntaxhighlight>  | |||
<br>  | |||
<code>QMessageBox</code>クラスにおいて、任意のアイコンを表示する場合は、以下のように記述する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 QMessageBox MsgBox(this);  | |||
 MsgBox.setText(text);  | |||
 MsgBox.setWindowTitle(tr("このプログラムについて"));  | |||
 MsgBox.setIconPixmap(QPixmap(":/images/logo.png"));  | |||
 MsgBox.exec();  | |||
 </syntaxhighlight>  | |||
<br><br>  | |||
== ステータスバー ==  | |||
ウインドウまたはダイアログにおいて、ステータスバーを表示する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 #include <QStatusBar>  | |||
 QStatusBar StatusBar;  | |||
 StatusBar->showMessage(tr("ステータスを表示中..."));  | |||
 </syntaxhighlight>  | |||
<br>  | |||
ステータスバーにプログレスバーを表示する場合、以下のように記述する。<br>  | |||
 <syntaxhighlight lang="c++">  | |||
 #include <QStatusBar>  | |||
 QStatusBar StatusBar;  | |||
 QProgressBar bar;  | |||
 StatusBar->addWidget(&bar);  | |||
 bar.setMinimum(0);  | |||
 bar.setMaximum(100);  | |||
 for(int i = 0; i < 100; i++)  | |||
 {  | |||
    bar.setValue(i);  | |||
    // 以下に処理を記述  | |||
    // ...  | |||
 }  | |||
 StatusBar->removeWidget(&bar);  | |||
  </syntaxhighlight>  |   </syntaxhighlight>  | ||
<br><br>  | <br><br>  | ||
2021年2月23日 (火) 23:23時点における最新版
概要
ダイアログの種類
下表に、Qtにおいて、標準で存在するダイアログの種類を示す。
| 用途 | クラス名 | 
|---|---|
| ファイル・ディレクトリ選択 | QFileDialog | 
| 色選択 | QFontDialog | 
| インプットボックス | QInputDialog | 
| プログレスバー | QProgressDialog | 
| 印刷関連 | QPrintDialog | 
| メッセージボックス | QMessageBox | 
ファイル・ディレクトリ選択ダイアログ
QFileDialogクラス
下表に、用途別にQFileDialogのメソッドを示す。
| メソッド | 用途 | 戻り値 | 
|---|---|---|
| getOpenFileName | ローカルファイル選択(開く) | QString | 
| getOpenFileNames | 複数ローカルファイル選択(開く) | QStringList | 
| getOpenFileUrl | リモートファイル選択(開く) | QUrl | 
| getOpenFileUrls | 複数リモートファイル選択(開く) | QList<QUrl> | 
| getSaveFileName | ローカルファイル選択(保存) | QString | 
| getSaveFileUrl | リモートファイル選択(保存) | QUrl | 
| getExistingDirectory | ローカルフォルダ選択 | QString | 
| getExistingDirectoryUrl | リモートフォルダ選択 | QUrl | 
フィルタを指定すると、拡張子で絞ってファイルを表示することができる。
# 書式フォーマット [書式];;見出し(拡張子1 拡張子2 ...) [;;見出し(拡張子1 ...)] # 例 すべて(*.*);;音声(*.wav *.wma *.mp3);;動画(*.wmv *.avi)
下表に、QFileDialogクラスのオプションを示す。(enum QFileDialog::Option)
| 定義 | 値 | 説明 | 
|---|---|---|
| ShowDirsOnly | 0x00000001 | フォルダのみ表示する。 ( FileModeがDirectoryの時に有効)
 | 
| DontResolveSymlinks | 0x00000002 | シンボリックリンクを解釈しない。 (指定しない場合、解釈する)  | 
| DontConfirmOverwrite | 0x00000004 | 既存ファイル選択時に確認画面を表示しない。 (指定しない場合、表示する)  | 
| DontUseNativeDialog | 0x00000010 | OS標準のダイアログを使用しない。 (指定しない場合、使用する)  | 
| ReadOnly | 0x00000020 | ReadOnlyを表示する。 | 
| HideNameFilterDetails | 0x00000040 | ファイル名フィルタの詳細が隠されているか示す。 | 
| DontUseCustomDirectoryIcons | 0x00000080 | ディレクトリのアイコンは常に標準のものを使用する。 ただし、カスタムアイコンを使用すると負荷が大きいため、 ディレクトリのアイコンは常に標準のものを使用した方がよい。  | 
※注意
シンボリックリンク(ショートカット)を選択しても、ディレクトリ欄には表示されない。
また、DontResolveSymlinksを指定すると、シンボリックリンク(ショートカット)を選択した場合、エラーメッセージを出力する。
指定しない場合、シンボリックリンク(ショートカット)を解釈するため、リンク先のファイルまたはディレクトリを選択したことになる。
ファイル選択ダイアログ
ファイルを開く(getOpenFileNameメソッド)
ファイルとディレクトリの一覧を表示する。
getOpenFileNameメソッドは、ファイルを1つ選択できる。
# 書式フォーマット [書式] 親, タイトル, パス, フィルター, 選択フィルタ, オプション
以下の例では、初期表示のパスを/home/<ユーザ名>、フィルタを2番目のフィルタ(*.txt)として表示する。
getOpenFileNameメソッドの戻り値には、選択したファイル名がフルパスで代入される。(キャンセルした場合、空文字が代入される)
変数SelFilterには、初期に選択するフィルターが入る。(キャンセルした場合、元のままになる)
 QString SelFilter = tr("テキスト(*.txt)");
 QString FileName = QFileDialog::getOpenFileName(this, tr("ファイルを開く"), "~/", tr("すべて(*.*);;テキスト(*.txt);;ソース(*.h *.cpp)"),
                                                 &SelFilter, QFileDialog::DontUseCustomDirectoryIcons);
 
 if(FileName.isEmpty())
 {  // キャンセル
    // キャンセル処理を記述
 }
また、引数を全て省略する場合、標準のダイアログが表示される。
標準のダイアログとは、タイトルは"開く"、初期表示のパスは"実行ファイルが存在するディレクトリ"となる。
また、フィルタ欄は表示されない。
 QString fileName = QFileDialog::getOpenFileName();
名前を付けて保存(getSaveFileNameメソッド)
getSaveFileNameメソッドを使用して、ファイルを1つ保存することができる。
既に同じ名前のファイルが存在する場合、上書きの確認メッセージが表示される。
[書式] getSaveFileName(親ウインドウのポインタ, ダイアログのタイトル, 初期表示のパス, フィルタ, 選択フィルタ, オプション)
パスに.(カレントディレクトリ)を指定する時、実行ファイルが存在するディレクトリを表示する。
getSaveFileNameメソッドの戻り値は、選択したファイル名のフルパスである。(キャンセルした場合、空文字となる)
選択フィルタ(下例では、変数SelFilter)には、選択したフィルタが代入される。(キャンセルした場合、元のままとなる)
選択フィルタ(下例では、変数SelFilter)を指定しない場合、フィルタの初期表示はフィルタの1つ目の要素(下例では、*.tif *.tiff)となる。
 QString SelFilter = "";
 QString FileName = QFileDialog::getSaveFileName(this, tr("名前を付けて保存"), ".", 
                                                 tr("TIFF image document(*.tif *.tiff);;Portable network graphic(*.png)"),
                                                 &SelFilter, QFileDialog::DontUseCustomDirectoryIcons);
 if(FileName.isEmpty())
 {  // キャンセル
    // キャンセル処理を記述
 }
getSaveFileNameメソッドの引数を全て省略する時、標準のダイアログが表示される。
この時、ダイログのタイトルは"名前を付けて保存"、初期表示のパスは"実行ファイルが存在するディレクトリ"となる。
また、フィルタ欄と既存ファイルの上書き確認メッセージは表示される。
 QString FileName = QFileDialog::getSaveFileName();
ディレクトリ選択ダイアログ(getExistingDirectoryメソッド)
getExistingDirectoryメソッドを使用して、ディレクトリの一覧を表示する。
ディレクトリを1つ選択することができる。
# 書式フォーマット [書式] getExistingDirectory(親ウインドウのポインタ, ダイアログのタイトル, 初期表示のパス, オプション)
QFileDialog::Optionsにおいて、ShowDirsOnlyを指定することで、ディレクトリのみ表示することができる。
getExistingDirectoryメソッドの戻り値は、選択したディレクトリ名のフルパスである。(キャンセルした場合、空文字となる)
また、以下のメッセージに対応するため、オプションにHideNameFilterDetailsを指定する。
selectNameFilter: Invalid parameter 'Directories' not found in 'All Files (*)'.
 QFileDialog::Options options = QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails | QFileDialog::DontUseCustomDirectoryIcons;
 QString DirName = QFileDialog::getExistingDirectory(this, tr("ディレクトリの選択"), "~/", options);
 
 if(DirName.isEmpty())
 {  // キャンセル
    // キャンセル処理を記述
 }
また、オプションにDontUseNativeDialogを指定する時、下図に示すダイアログが表示される。
getExistingDirectoryメソッドの引数を全て省略する場合、標準のダイアログが表示される。
この時、タイトルは"フォルダーの選択"、初期表示のパスは"実行ファイルが存在するディレクトリ"となる。
 QString DirName = QFileDialog::getExistingDirectory();
色選択ダイアログ(QColorDialogクラス)
RGBを10進または16進で入力できる色選択ダイアログである。
getColorメソッドを使用すると、Qt標準の色選択ダイアログを表示する。
[書式] getColor(色, 親ウインドウのポインタ, ダイアログのタイトル, オプション)
以下の例では、初期表示として、青で透明度を指定している。
getColorメソッドの戻り値は、選択した色情報クラスである。(キャンセルした場合、Validがfalseになる)
色は、#AARRGGBB形式、#RRGGBB形式、Qt定義色(Qt::red等)で指定する。
透明度(AA、アルファチャンネル)を省略する時、初期値は255となる。
ShowAlphaChannelオプションを指定しない場合、AAに初期値を指定しても戻り値は固定でFF(255)となる。
 QColor color = QColorDialog::getColor("#800a64c8", this, tr("色選択"), QColorDialog::ShowAlphaChannel);
 
 if(color.isValid())
 {
    // color.name();  → "#0a64c8" (#RRGGBB)
    // color.name(QColor::HexArgb);  → "#800a64c8" (#AARRGGBB)
    // int r, g, b, a;
    // color.getRgb(&r, &g, &b, &a);  → r=10, g=100, b=200, a=128
 }
QColorDialogのオプション(enum QColorDialog::ColorDialogOption)
| オプション名 | 値 | 説明 | 
|---|---|---|
| ShowAlphaChannel | 0x00000001 | アルファチャンネル(透明度)を表示する。 | 
| NoButtons | 0x00000002 | OKとキャンセルのボタンを表示しない。 (ライブダイアログで役立つ)  | 
| DontUseNativeDialog | 0x00000004 | OS標準ではなくQt標準の色選択を使用する。 (指定しない場合、有効)。  | 
getColorメソッドの引数を全て省略する時、標準のダイアログが表示される。
この時、標準ダイアログのタイトルは"Select Color"、色は白(#ffffff)、アルファチャンネルの項目は無い。
 QColor color = QColorDialog::getColor();
フォント選択ダイアログ(QFontDialog)
フォント選択ダイアログは、フォントを選択できるダイアログである。
QFontDialogクラスのgetFontメソッドは、Qt標準のフォント選択ダイアログを表示する。
[書式1] getFont(結果, 初期フォント, 親ウインドウのポインタ, ダイアログのタイトル, オプション) [書式2] getFont(結果, 親ウインドウのポインタ)
以下の例では、初期フォントを18pxのCourier、等幅フォントとしている。
getFontメソッドの戻り値は、選択したフォント情報のクラスである。(キャンセルした場合、第1引数はfalseとなる)
[Esc]キーを押下する場合は、キャンセルしたものと見なされる。
 bool ok;
 QFont font = QFontDialog::getFont(&ok, QFont("Courier", 18), this, tr("フォント選択"), QFontDialog::MonospacedFonts);
 
 if(ok)
 {
    // font.family();  → "Courier"
    // font.pointSize();  → 18
    // font.italic();  → false (true:Font styleがItalic)
    // font.bold();  → false (true:Font styleがBold)
    // font.weight();  → 50 (bold()=trueの時は75)
    // font.strikeOut();  → false (true:EffectsのstrikeOutオン)
    // font.underline();  → false (true:Effectsのunderlineオン)
 }
QFontDialogクラスのオプション(enum QFontDialog::FontDialogOption)
| オプション名 | 値 | 説明 | 
|---|---|---|
| NoButtons | 0x00000001 | [OK]ボタンと[キャンセル]ボタンを表示しない。 (ライブダイアログで役立つ) ただし、ダイアログ右上の[閉じる]ボタンが使用できなくなる。  | 
| DontUseNativeDialog | 0x00000002 | OS標準ではなくQt標準のフォント選択を使用する。 指定しない場合、Qt標準のフォント選択を使用する。  | 
| ScalableFonts | 0x00000004 | スケーラブルフォントを表示する。 スケーラブルフォントとは、拡大縮小しても精度の変わらないフォントである。  | 
| NonScalableFonts | 0x00000008 | スケーラブルフォント以外を表示する。 | 
| MonospacedFonts | 0x00000010 | 等幅フォントを表示する。 | 
| ProportionalFonts | 0x00000020 | 可変幅フォントを表示する。 | 
第1引数は必須であり、他の引数を全て省略する時、標準のフォント選択ダイアログが表示される。
この時、ダイアログのタイトルは"Select Font"、使用可能なフォントをアルファベット順に並べて、その先頭が選択された状態となる。
 bool ok;
 QFont font = QFontDialog::getFont(&ok);
インプットダイアログ
印刷ダイアログ
QPrintDialogクラス
印刷ダイアログにおいて、使用する場合は以下のヘッダファイルをインクルードする必要がある。
#include <QtPrintSupport>
また、プロジェクトファイル(.proファイル)に、以下のモジュールを追記する必要がある。
QT += core gui printsupport
下表に示すように、印刷ダイアログには、様々な支援クラスがある。
印刷ダイアログを使用する場合は、描画デバイスが必要である。
ページ設定等は、印刷ダイアログに組み込まれている。
印刷関連クラス
| クラス名 | 説明 | 
|---|---|
| QAbstractPrintDialog | 印刷ダイアログの抽象クラス | 
| QPageSetupDialog | ページ設定 | 
| QPrintDialog | 印刷ダイアログ | 
| QPrintEngine | 印刷サブシステムとのインターフェース定義 | 
| QPrintPreviewDialog | 印刷出力レイアウトのプレビューダイアログ | 
| QPrintPreviewWidget | 印刷プレビューウィジェット | 
| QPrinter | プリンタに出力する描画デバイス | 
| QPrinterInfo | 既存プリンタの情報 | 
テキスト印刷
文字の印刷は、QTextDocumentを使用すると簡単にできる。
QTextEditクラス等は、QTextDocumentを取得できるので、テキストをセットする手間が省ける。
 QPrinter printer(QPrinter::HighResolution);
 
 QPrintDialog dialog(&printer, this);
 if(dialog.exec() == QDialog::Accepted)
 {
    QTextDocument doc;
    doc.setPlainText("テキスト印刷のサンプルです。\n改行しました。");
    doc.print(&printer);
 }
画像印刷
以下の例では、画像ファイル(image.jpgファイル)の縦横比を崩さずに、できるだけ大きなサイズで印刷している。
- 印刷領域の横と縦から、縦横比を崩さずに画像が収まるサイズを求める。
 - 求めたサイズで、印刷領域の横と縦を変更する。
 - 描画領域を画像サイズにして画像を描けば、自動的にサイズ調整と印刷領域への転送が行われる。
 
setViewportメソッドを使用して、印刷領域のサイズを変更しない場合、縦横比が崩れる。setWindowメソッドを使用して、描画領域のサイズを変更しない場合、小さな画像になる。
 QPrinter printer(QPrinter::ScreenResolution);
 
 QPrintDialog dialog(&printer, this);
 if(dialog.exec() == QDialog::Accepted)
 {
    QPainter painter(&printer);
    QRect rect = painter.viewport();
    QPixmap pixmap("~/tmp/image.jpg");
    QSize size = pixmap.size();
    size.scale(rect.size(), Qt::KeepAspectRatio);
 
    painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
    painter.setWindow(pixmap.rect());
    painter.drawPixmap(0, 0, pixmap);
 }
ウィジェット印刷
以下の例では、縦横比を崩さずに、横200pxでwidgetを印刷している。
widgetクラスのgrabメソッドを使用して、QPixmapクラスを生成する。(widgetの子要素も含まれる)- 生成した
QPixmapクラスの横を200pxにして描画する。縦は横に合わせて自動的に伸縮される。 
 QPrinter printer(QPrinter::ScreenResolution);
 
 QPrintDialog dialog(&printer, this);
 if(dialog.exec() == QDialog::Accepted)
 {
    QPixmap pixmap = widget->grab();
    QPainter painter(&printer);
    painter.drawPixmap(0, 0, pixmap.scaledToWidth(200));
 }
印刷プレビュー
以下の例では、用紙にA4縦を指定して印刷プレビューを表示している。
実際の描画は、redrawPreviewメソッド(ユーザ定義メソッド)で行う。
用紙のサイズと向きは、プレビュー画面で設定できるため、省略可能である。
プレビュー画面のサイズを指定しないと、とても小さな表示になるので注意すること。
設定変更による描画要求シグナルには、redrawPreviewメソッド(ユーザ定義メソッド)を接続する。
execメソッドを使用して、印刷プレビュー画面を表示する。(プレビュー画面を閉じるまで制御は戻らない)
 // mainwindow.cpp
 
 QPrinter printer(QPrinter::HighResolution);
 printer.setPaperSize(QPrinter::A4);
 printer.setOrientation(QPrinter::Portrait);
 
 QPrintPreviewDialog preview(&printer, this);
 preview.setFixedSize(this->width() - 100, this->height());
 connect(&preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(redrawPreview(QPrinter*)));
 
 preview.exec();
描画関数redrawPreviewメソッド(ユーザ定義メソッド)は、ヘッダファイルのスロットで宣言する。
 // mainwindow.h
 
 private slots:
    void redrawPreview(QPrinter *printer);
以下の例では、メイン画面のハードコピーを印刷プレビューに表示している。
用紙全体がプレビュー画面に収まるように、自動的に縮小表示される。
[ページ設定]画面の用紙の向きを変更する場合、自動的に伸縮率が変化する。
QPixmapクラスの生成以外は、画像印刷と同じ処理となる。
 void MainWindow::redrawPreview(QPrinter *p)
 {
    QPainter painter(p);
    QRect rect = painter.viewport();
    QPixmap pixmap = this->grab();
    QSize size = pixmap.size();
    size.scale(rect.size(), Qt::KeepAspectRatio);
 
    painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
    painter.setWindow(pixmap.rect());
    painter.drawPixmap(0, 0, pixmap);
 }
画像の印刷解像度(dpi)を設定する
画像ファイルで見かける解像度は、印刷解像度である。
すなわち、dpiとは紙上1インチに表現する画素数の値のことである。
例えば、1440[px] x 1440[px]、72[dpi]の画像を印刷する場合、紙上のサイズは、1440[px] / 72[dpi] = 20[inch] = 508[mm]となる。
以下の例では、上記の値をQImageクラスに設定して保存している。
 // ドット / メートルに変換(72dpiの場合)
 int dpm = 72 / 0.0254;
 
 // 水平方向と垂直方向を別個に指定できる
 qimg.setDotsPerMeterX(dpm);
 qimg.setDotsPerMeterY(dpm);
  
 // dpiをファイル内に保持できるフォーマットのみ保存できる
 qimg.save(arrPath, "JPEG", -1);
プログレスバーダイアログ
QProgressDialogクラスを使用して、標準で用意されているプログレスバーダイアログを表示する。
QProgressDialogクラスの最後の引数はウインドウフラグであるが、ここでは使用しないため省略している。
[書式1] QProgressDialog <変数名>(親ウインドウのポインタ) [書式2] QProgressDialog <変数名>(表示文字列, キャンセルボタン文字列, 最小値, 最大値, 親ウインドウのポインタ)
以下の例では、プログレスバーにおいて、500[ms]ごとに10%ずつ増加させて表示している。
 QProgressDialog ProgressDlg(tr("しばらくお待ちください・・・"), tr("キャンセル"), 0, 200, this);
 ProgressDlg.setWindowModality(Qt::WindowModal);
 ProgressDlg.setWindowTitle(tr("処理中"));
 ProgressDlg.show();
 
 for(int cnt = 0; cnt < 200; cnt += 20)
 {
    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
    ProgressDlg.setValue(cnt);
 
    if(ProgressDlg.wasCanceled())
    {
       break;
    }
 
    Sleep(500);
 }
 
 progress.setValue(200);
また、全ての引数を省略する場合、標準のプログレスバーダイアログが表示される。
表示文字列は無し、キャンセルボタンのラベル名は"Cancel"、プログレスバーの最小値は0、最大値は100となる。
 QProgressDialog progress;
モーダルダイアログ
 // mainwindow.cpp
 void MainWindow::OnBtnClicked()
 {
    ModalDialog ModalDlg;
    ModalDlg.setModal(true);
    ModalDlg.exec();
 }
モードレスダイアログ
 // mainwindow.h
 
 #ifndef MAINWINDOW_H
 #define MAINWINDOW_H
 
 #include <QMainWindow>
 #include "ModelessDialog.h"
 
 namespace Ui
 {
    class MainWindow;
 }
 
 class MainWindow : public QMainWindow
 {
    Q_OBJECT
 
 public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
 private slots:
    void on_pushButton_clicked();
 
 private:
    Ui::MainWindow *ui;
    std::unique_ptr<ModelessDialog> ModelessDlg;
 };
 
 #endif // MAINWINDOW_H
 // mainwindow.cpp
 
 void MainWindow::OnBtnClicked()
 {
    ModelessDlg = std::make_unique<ModelessDialog>(this);
    ModelessDlg->show();
 }
モードレスダイアログ等を常に前面に表示する場合は、以下のように記述する。
 ModelessDlg = std::make_unique<ModelessDialog>(this);
 
 ModelessDlg->setWindowFlags(Qt::WindowStaysOnTopHint);
 
 ModelessDlg->show();
カスタムダイアログ
カスタムダイアログは、自由にレイアウト可能なダイアログである。
QDialogクラスを使用して作成することができる。
以下の例では、メール送信用のダイアログを作成している。(ただし、レイアウトと結果の取得のみ対応)
[OK]ボタンを押下する時、acceptedシグナルが発行されて、[CANCEL]ボタンを押下する時、rejectedシグナルが発行される。
各スロットは標準で用意されているため、任意の処理を記述せずに1または0を返す。
また、サイズグリップは表示されないが、ウインドウのサイズは自由に変更できる。
 QFormLayout Form();
 Form.setLabelAlignment(Qt::AlignRight);
 Form.addRow(tr("送信先 :"), new QLineEdit);
 Form.addRow(tr("件名 :"), new QLineEdit);
 Form.addRow(tr("本文 :"), new QTextEdit);
 
 QDialogButtonBox BtnBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
 BtnBox.button(QDialogButtonBox::Ok)->setText(tr("送信"));
 BtnBox.button(QDialogButtonBox::Cancel)->setText(tr("閉じる"));
 
 QVBoxLayout vbox;
 vbox.addLayout(Form);
 vbox.addWidget(BtnBox);
 
 QDialog Dlg(this);
 Dlg.setModal(true);
 Dlg.setWindowTitle(tr("メール送信"));
 Dlg.setLayout(vbox);
 
 connect(BtnBox, SIGNAL(accepted()), Dlg, SLOT(accept()));
 connect(BtnBox, SIGNAL(rejected()), Dlg, SLOT(reject()));
 
 // 1 : Ok(送信), 0 : Cancel(閉じる)
 int iRet = Dlg.exec();
以下の例では、6つの選択ボタンを表示している。
各ボタンにはプロパティを設定してボタン番号を設定する。(buttonNoは任意の名前である)
全てのボタンのイベントは、スロットexitDialogで処理する。
最小サイズと最大サイズを同じ値に設定することで、ダイアログのサイズを固定している。
サイズグリップをオフにしても、サイズ変更不可にはならない。
ダイアログ右上の[x]ボタンを押下した場合、buttonは0になる。
 QStringList List;
 List << "グルメツアー" << "買い物ツアー" << "農業体験ツアー";
 List << "工場見学" << "寺社巡り" << "歴史に触れる旅";
 
 QLabel Label("コースを選択してください。");
 Label.setFixedHeight(30);
 
 QGridLayout Grid;
 Grid.setContentsMargins(20, 16, 20, 24); // left, top, right, bottom
 Grid.setHorizontalSpacing(20);
 Grid.setVerticalSpacing(0);
 
 for(int i = 0; i < 3; i++)
 {
    QLabel LabelCourse(QString((int)'A' + i) + " コース");
    LabelCourse.setFixedHeight(20);
    Grid.addWidget(LabelCourse, 0, i, Qt::AlignHCenter);
 
    QPushButton Btn(List[i]);
    Btn.setFixedSize(150, 40);
    Btn.setStyleSheet("background:green; color:lightyellow;");
    Btn.setProperty("buttonNo", i + 1);
 
    connect(&Btn, SIGNAL(clicked()), this, SLOT(exitDialog()));
 
    Grid.addWidget(&Btn, 1, i, Qt::AlignHCenter);
 }
 
 Grid.addWidget(new QLabel(""), 2, 0, 1, 3);
 
 for(int i = 0; i < 3; i++)
 {
    QLabel *label = new QLabel(QString((int)'D' + i) + " コース");
    label->setFixedHeight(20);
    Grid.addWidget(label, 3, i, Qt::AlignHCenter);
 
    QPushButton *pbtn = new QPushButton(list[i+3]);
    pbtn->setFixedSize(150, 40);
    pbtn->setStyleSheet("background:green; color:lightyellow;");
    pbtn->setProperty("buttonNo", i + 3 + 1);
 
    connect(pbtn, SIGNAL(clicked()), this, SLOT(exitDialog()));
 
    Grid.addWidget(pbtn, 4, i, Qt::AlignHCenter);
 }
 
 QWidget Widget;
 Widget.setLayout(&Grid);
 Widget.setStyleSheet("background:lightyellow;");
 
 QPushButton BtnQuit("どれも選ばない");
 BtnQuit.setProperty("buttonNo", 0);
 connect(&BtnQuit, SIGNAL(clicked()), this, SLOT(exitDialog()));
 
 QVBoxLayout vbox;
 vbox.addWidget(Label);
 vbox.addWidget(Widget);
 vbox.addStretch();
 vbox.addWidget(BtnQuit);
 
 QDialog Dlg(this);
 Dlg.setModal(true);
 Dlg.setWindowTitle(tr("ご案内"));
 Dlg.setSizeGripEnabled(false);
 Dlg.setMinimumSize(560, 290);
 Dlg.setMaximumSize(560, 290);
 Dlg.setLayout(vbox);
 
 // 0 : 選択しない, 1~6 : グルメ ~ 歴史に触れる
 int iRet = Dlg.exec();
mainwindow.hファイルにスロットの宣言を記述する。
 // mainwindow.h
 
 private slots:
    void exitDialog();
スロットの処理を記述する。
シグナルの送信元を調べて、QDialogであれば閉じる。
送信元のウインドウがQDialogではない場合、処理は実行しない。
buttonNoプロパティの値を取得してdoneメソッドを実行すると、ダイアログを閉じてexecメソッドの戻り値に変数iNoを渡す。
 // mainwindow.cpp
 
 void MainWindow::exitDialog()
 {
    QWidget *Window = static_cast<QWidget *>(sender())->window();
 
    if(win->inherits("QDialog"))
    {
       QDialog *Dlg = static_cast<QDialog *>(win);
       int iNo = (sender()->property("buttonNo")).toInt();
       Dlg->done(iNo);
    }
 }
メッセージボックス(QMessageBoxクラス)
QMessageBoxクラスを使用して、メッセージボックスを表示する。
[書式] QMessageBox <変数名>(親ウインドウのポインタ, タイトル, 表示文字列, ボタン, デフォルト)
QMessageBoxクラスのアイコン(enum QMessageBox::Icon)
| アイコン | 値 | 説明 | 標準Pixmap | 
|---|---|---|---|
| NoIcon | 0 | アイコンなし | |
| Information | 1 | 情報 | SP_MessageBoxInformation | 
| Warning | 2 | 警告 | SP_MessageBoxWarning | 
| Critical | 3 | 重大な問題 | SP_MessageBoxCritical | 
| Question | 4 | 質問 | SP_MessageBoxQuestion | 
簡素なメッセージボックス
状況に応じて、以下に示す4種類を使い分ける。
変数iRetには、QMessageBox::YesまたはQMessageBox::Noのいずれかが入る。
また、QMessageBox::questionは、ボタンを指定しない場合でも[Yes]ボタンと[No]ボタンが表示される。
 QMessageBox::information(this, tr("情報"), tr("メッセージ"));
 QMessageBox::warning(this, tr("警告"), tr("メッセージ"));
 QMessageBox::critical(this, tr("致命的エラー"), tr("メッセージ"));
 
 int iRet = QMessageBox::question(this, tr("確認"), tr("メッセージ"));
標準のメッセージボックス
複数のボタンを表示して選択されたボタンを返す。
書式1は最初の3つの引数が必須、書式2は必要な情報を後で指定する。
書式1の最後の引数にはウインドウフラグがあるが、ここでは省略している。
[書式1] QMessageBox <変数名>(アイコン, タイトル, 表示文字列, ボタン, 親ウインドウのポインタ) [書式2] QMessageBox <変数名>(親ウインドウのポインタ)
以下の例では、上記の書式1の形式でメッセージボックスを表示している。
 QMessageBox MsgBox(QMessageBox::Question, tr("確認"), tr("これでよろしいですか?"), 
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, this);
 
 int iRet = MsgBox.exec();
以下の例では、上記の書式2の形式でメッセージボックスを表示している。
setDefaultButtonメソッドにより、標準でフォーカスが当たるボタンを指定できる。
 QMessageBox MsgBox(this);
 
 MsgBox.setIcon(QMessageBox::Question);
 MsgBox.setWindowTitle(tr("確認"));
 MsgBox.setText(tr("これでよろしいですか?"));
 MsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
 MsgBox.setDefaultButton(QMessageBox::Cancel);
 MsgBox.setButtonText(QMessageBox::Yes, tr("OK"));
 MsgBox.setButtonText(QMessageBox::No, tr("Cancel"));
 MsgBox.setButtonText(QMessageBox::Cancel, tr("Back"));
 
 int iRet = MsgBox.exec();
ボタンについて
QMessageBoxクラスでは、様々なボタンが用意されている。
各ボタンには意味があるため、それに応じて使用する必要がある。
ボタンは記述した順番で並ぶわけではないので注意すること。
[Cancel]ボタンを記述しない場合、メッセージボックス右上の[x]ボタンが使用できなくなる可能性がある。
QMessageBoxクラスのボタン(enum QMessageBox::StandardButton)
| ボタン名 | 値 | 説明 | 役割名 | 
|---|---|---|---|
| Ok | 0x00000400 | 了解 | AcceptRole | 
| Open | 0x00002000 | 開く | AcceptRole | 
| Save | 0x00000800 | 保存 | AcceptRole | 
| Cancel | 0x00400000 | キャンセル | RejectRole | 
| Close | 0x00200000 | 閉じる | RejectRole | 
| Discard | 0x00800000 | 破棄または保存しない | DestructiveRole | 
| Apply | 0x02000000 | 現在の変更を適用する | ApplyRole | 
| Reset | 0x04000000 | リセット | ResetRole | 
| RestoreDefaults | 0x08000000 | デフォルトに戻す | ResetRole | 
| Help | 0x01000000 | ヘルプ | HelpRole | 
| SaveAll | 0x00001000 | 全て保存 | AcceptRole | 
| Yes | 0x00004000 | はい | YesRole | 
| YesToAll | 0x00008000 | 全てはい | YesRole | 
| No | 0x00010000 | いいえ | NoRole | 
| NoToAll | 0x00020000 | 全ていいえ | NoRole | 
| Abort | 0x00040000 | 異常終了 | RejectRole | 
| Retry | 0x00080000 | 再試行 | AcceptRole | 
| Ignore | 0x00100000 | 無視 | AcceptRole | 
| NoButton | 0x00000000 | ボタンなし | 無効 | 
下表に、各ボタンの役割を示す。
QMessageBoxクラスのボタンの役割(enum QMessageBox::ButtonRole)
| ロール名 | 値 | 説明 | 
|---|---|---|
| InvalidRole | -1 | 無効 | 
| AcceptRole | 0 | 同意および受諾 (OK, Save, SaveAll, Open, Retry, Ignore)  | 
| RejectRole | 1 | 拒否 (Abort, Close, Cancel)  | 
| DestructiveRole | 2 | 変更を破棄して閉じる。 (Discard)  | 
| ActionRole | 3 | ダイアログ内の要素を変更する。 | 
| HelpRole | 4 | ヘルプ要求 (Help)  | 
| YesRole | 5 | 受諾または全て受諾 (Yes, YesToAll)  | 
| NoRole | 6 | 拒否または全て拒否 (No, NoToAll)  | 
| ResetRole | 7 | ダイアログ内の項目をデフォルトに戻す。 (Reset, RestoreDefaults)  | 
| ApplyRole | 8 | 変更を適用する。 (Apply)  | 
プッシュボタン追加
メッセージボックスに任意のボタンを追加する場合、以下のように記述する。
任意のボタンでは、役割も指定する必要がある。
 QMessageBox MsgBox(this);
 
 QPushButton *anyButton = MsgBox.addButton(tr("hoge"), QMessageBox::ActionRole);
 
 MsgBox.setWindowTitle(tr("hogeボタンの表示"));
 MsgBox.setText(tr("メッセージ"));
 MsgBox.exec();
 
 if(MsgBox.clickedButton() == anyButton)
 {  // [hoge]ボタンが押下された場合
    // 処理を記述
 }
概要ダイアログ
Qtのライセンス等の情報を表示する。
 QMessageBox MsgBox;
 MsgBox.aboutQt(this, tr("Qtについて"));
以下の例では、ソフトウェアの説明を表示している。
aboutメソッドでは、必ずソフトウェアのアイコンが表示される。
 QString strOverView = "<span style=\"font-weight:bold\">Qtサンプル画面</span><br><br>"
                       "このプログラムはQt C++で作成したものです。<br>"
                       "いろいろなレイアウトやウィジェットの使用例が入っています。<br><br>"
                       "※ご注意<br>"
                       "必ずしもこの使用法が正しいとは限りません。<br>"
                       "自分で使うプログラムとしては十分動くというだけです。<br>"
                       "何の保証もありませんので、自己責任でお使いください。<br><br>"
                       "Top Page: "
                       "<a href=\"http://www.sample.com/index.html\">"
                       "http://dorafop.my.coocan.jp/index.html</a>";
 
 QMessageBox MsgBox;
 MsgBox.about(this, tr("このプログラムについて"), strOverView);
QMessageBoxクラスにおいて、任意のアイコンを表示する場合は、以下のように記述する。
 QMessageBox MsgBox(this);
 MsgBox.setText(text);
 MsgBox.setWindowTitle(tr("このプログラムについて"));
 MsgBox.setIconPixmap(QPixmap(":/images/logo.png"));
 
 MsgBox.exec();
ステータスバー
ウインドウまたはダイアログにおいて、ステータスバーを表示する。
 #include <QStatusBar>
 
 QStatusBar StatusBar;
 StatusBar->showMessage(tr("ステータスを表示中..."));
ステータスバーにプログレスバーを表示する場合、以下のように記述する。
 #include <QStatusBar>
 
 QStatusBar StatusBar;
 QProgressBar bar;
 StatusBar->addWidget(&bar);
 
 bar.setMinimum(0);
 bar.setMaximum(100);
 for(int i = 0; i < 100; i++)
 {
    bar.setValue(i);
    // 以下に処理を記述
    // ...
 }
 
 StatusBar->removeWidget(&bar);