📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の9版が非表示)
276行目: 276行目:
  bool ok;
  bool ok;
  QFont font = QFontDialog::getFont(&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>
332行目: 540行目:
     ModelessDlg = std::make_unique<ModelessDialog>(this);
     ModelessDlg = std::make_unique<ModelessDialog>(this);
     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>
  </syntaxhighlight>
543行目: 908行目:
   
   
  MsgBox.exec();
  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>