Qt入門:初心者向けGUIプログラミングの第一歩

はい、承知いたしました。Qt入門:初心者向けGUIプログラミングの第一歩に関する詳細な説明を含む記事を作成します。約5000語を目指し、初心者にも分かりやすいように、概念の説明、環境構築、最初のアプリケーション作成から基本的な要素までを網羅します。

以下に記事本文を表示します。


Qt入門:初心者向けGUIプログラミングの第一歩

はじめに:なぜGUIプログラミングを学ぶのか

現代のソフトウェアは、ほとんどの場合、ユーザーが視覚的に操作できるインターフェース、すなわちGUI(Graphical User Interface)を備えています。コマンドラインやテキストベースの操作に比べて、直感的で分かりやすく、多くのユーザーにとって使いやすいからです。あなたが今この記事を読んでいるウェブブラウザも、デスクトップ上で動いているアプリケーションも、スマートフォンのアプリも、そのほとんど全てがGUIを持っています。

GUIプログラミングは、画面上にボタン、テキストボックス、ウィンドウなどの要素(これを「ウィジェット」と呼びます)を配置し、それらがユーザーの操作(クリック、キー入力など)に反応して動作するようにコードを書くことです。一見複雑に思えるかもしれませんが、適切なツールとフレームワークを使えば、初心者でも比較的容易に始めることができます。

では、数あるGUIツールキットの中で、なぜ「Qt」を選ぶのでしょうか?

Chapter 1: Qtの世界へようこそ

1.1 Qtとは何か?

Qt(キュート)は、C++で書かれたクロスプラットフォームアプリケーション開発フレームワークです。単にGUIアプリケーションを作るだけでなく、ネットワーク通信、データベース連携、XML処理、マルチメディア、WebGL、組み込み開発など、幅広い機能を提供しています。その歴史は古く、1995年にノルウェーのTrolltech社(現在はThe Qt Company)によって開発が始まりました。

Qtは、Windows、macOS、Linux、Android、iOSなどの主要なデスクトップおよびモバイルプラットフォーム、さらには組み込みシステムや特殊なリアルタイムOSなど、非常に多岐にわたる環境で動作するアプリケーションを単一のコードベースから開発できることが最大の強みの一つです。

1.2 Qtの主な特徴と利点

Qtが多くの開発者に選ばれるのには、以下のような理由があります。

  • クロスプラットフォーム性: 前述の通り、一度書いたコードを様々なOSでほとんど変更なく動作させられます。これは開発コストと時間を大幅に削減します。
  • 豊富な機能: GUIウィジェットだけでなく、ファイル操作、ネットワーク、スレッド、XML/JSON処理、データベースアクセス、OpenGL/Vulkanによるグラフィックス描画、オーディオ/ビデオ再生など、アプリケーション開発に必要なあらゆる機能がモジュールとして提供されています。標準ライブラリやOS固有のAPIに頼ることなく、Qt内で完結できることが多いです。
  • 直感的で強力なGUI開発ツール「Qt Designer」: ドラッグ&ドロップ操作でGUI画面を設計できます。これにより、コードを書く前に画面のレイアウトやデザインを視覚的に確認・調整できます。
  • 優れたシグナル&スロット機構: Qt独自のイベント処理機構です。オブジェクト間で発生した「シグナル」(例: ボタンがクリックされた)と、それに対応する処理を行う「スロット」(例: テキストを変更する関数)を柔軟に接続できます。これにより、コード間の結合度を低く保ちながら、複雑なイベント駆動型プログラムを記述できます。
  • C++ベースの高いパフォーマンス: C++で書かれているため、ネイティブアプリケーションに匹敵する高い実行速度を実現します。また、Qt独自の拡張(moc: Meta-Object Compiler)により、C++の標準機能だけでは難しいシグナル&スロットやプロパティシステムを実現しています。
  • 洗練されたAPI設計: Qtのクラスや関数は、一貫性があり、使いやすいように設計されています。ドキュメントも非常に充実しています。
  • 強力な開発環境「Qt Creator」: Qt開発のために特別に設計された統合開発環境(IDE)です。コードエディタ、GUIデザイナー、デバッガ、プロジェクト管理ツールなどが統合されており、開発を効率的に進められます。
  • ライセンス: LGPLやGPLといったオープンソースライセンス、および商用ライセンスが提供されています。オープンソースプロジェクトや、LGPLの条件を満たす商用アプリケーションであれば無償で利用開始できます。

1.3 Qtのライセンスについて(簡単な説明)

Qtはデュアルライセンスモデルを採用しています。

  • 商用ライセンス: アプリケーションのソースコードを公開せずに商用利用したい場合に必要です。
  • オープンソースライセンス: LGPL (Lesser General Public License) または GPL (GNU General Public License) です。これらのライセンスに基づき、Qt自体を改変しない限り、多くの場合無償で利用できます。特にLGPL版は、Qtライブラリをダイナミックリンク(共有ライブラリとして利用)し、かつQtを利用している部分のソースコードを公開しない限り、開発するアプリケーションのソースコードを非公開とすることができます(ただし、Qtのライブラリ自体をユーザーが置き換えられるようにするなどの条件があります)。

初めてGUIプログラミングを学ぶ、趣味でアプリケーションを作る、オープンソースとして公開するといった目的であれば、多くの場合LGPL版で始めることができます。この記事では、オープンソースライセンスでの利用を前提とします。

Chapter 2: 開発環境の準備:Qtのインストール

Qtを使った開発を始めるには、まず必要なツールとライブラリをコンピュータにインストールする必要があります。Qt Companyが提供する「Qt Online Installer」を使うのが最も一般的で簡単な方法です。

2.1 Qt Online Installerのダウンロード

Qtの公式サイト (https://www.qt.io/) にアクセスします。「Downloads」または「Get started for free」のようなリンクを探します。通常、個人開発者や学習目的であれば、”Qt for Open Source Development” のダウンロードリンクを探します。

ダウンロードページでは、お使いのOS(Windows, macOS, Linux)に合ったインストーラーを選択してください。通常、「Qt Online Installer for [Your OS]」のような名前で見つかります。

2.2 インストール手順(Windowsを例に説明)

ダウンロードしたインストーラーを実行します。ウィザード形式で進みます。

  1. Qt Account: Qtアカウントの作成またはログインを求められます。オープンソース版を利用する場合でもアカウントは必要です。画面の指示に従って作成・ログインしてください。
  2. Welcome / Introduction: 歓迎メッセージが表示されます。次へ進みます。
  3. Installation Folder: Qtをインストールするフォルダを選択します。デフォルトの場所(例: C:\Qt)で問題なければそのまま、変更したい場合は参照ボタンで指定します。パスに日本語やスペースが含まれないようにするのが無難です。
  4. Select Components: ここが最も重要です。 どのバージョンのQt、どのコンポーネントをインストールするかを選択します。
    • Qt Version: 複数のQtバージョンがリストされます。通常は最新の安定版(LTSなどと表示されているもの)を選べば良いでしょう。例えば、「Qt 6.5.2」のような項目を展開します。
    • Component Selection: 展開したQtバージョンの下に、さらに多くの項目が表示されます。初心者が必要とする主要なコンポーネントは以下の通りです。
      • MSVC [バージョン] 64-bit (または MinGW [バージョン] 64-bit): Windowsの場合、これはいわゆる「Kit」と呼ばれるもので、特定のコンパイラ(Microsoft Visual C++ または MinGW-w64)とQtライブラリの組み合わせです。通常、開発環境(Visual StudioやMinGW)に合わせて選びますが、特にこだわりがなければ最新のMSVC版、またはMinGW版を選んでおけば良いでしょう。WindowsでGCCを使いたい場合はMinGW版を選択します。(macOSならclang 64-bit、Linuxならgcc 64-bitのような項目を選びます)。
      • Qt Charts, Qt Data Visualization, etc.: これらは追加モジュールです。最初は必須ではありませんが、将来使う可能性があるならインストールしても良いでしょう。容量を節約するならチェックを外します。
      • Qt Designer, Qt Linguist, Qt Assistant: これらは開発ツールです。これらはGUI開発に役立つため、必ずインストールしてください。 通常は「Developer and Designer Tools」などのグループに含まれています。
      • Qt Creator [バージョン]: QtのIDEです。必ずインストールしてください。
      • MinGW [バージョン] or CMake (if not selected as a Kit): コンパイラやビルドシステムです。Kitとして選択したものと同じ種類のものが自動的に選択されることが多いですが、必要に応じて確認します。
    • Recommendations: インストーラーが推奨するコンポーネントも参考にしてください。
    • 最低限必要なもの: Qt Creator、Qt本体のバージョン(Kitを含む)、開発ツール(Designerなど)。これらが選択されていることを確認します。
  5. License Agreement: ライセンス同意を確認し、同意します。オープンソースライセンス(LGPL/GPL)を選択してください。
  6. Ready to Install: インストール概要が表示されます。確認して「Install」をクリックします。
  7. Installation: ダウンロードとインストールが始まります。インターネット接続が必要です。完了するまで待ちます。
  8. Installation Finished: インストールが完了しました。「Launch Qt Creator」にチェックが入っていることを確認し、「Finish」をクリックするとQt Creatorが起動します。

2.3 トラブルシューティングのヒント

  • インストール失敗: インターネット接続が安定しているか確認します。ファイアウォールやプロキシの設定がインストーラーの通信を妨げていないか確認します。管理者権限で実行してみてください。
  • Qt Creator起動時にキットが見つからない: インストール時に適切なKit(コンパイラとQtバージョンの組み合わせ)が選択されなかった可能性があります。Qt Maintenance Tool(インストールフォルダにあるはずです)を起動し、「Add or remove components」からKitを追加インストールしてみてください。
  • ビルドエラー: コンパイラが正しく設定されていない、パスが通っていない、環境変数が間違っているなどが考えられます。Qt Creatorの「Options」->「Kits」設定を確認し、選択したKitに必要なコンパイラやデバッガが検出されているか確認します。

インストールが成功し、Qt Creatorが起動すれば、開発の準備は完了です。

Chapter 3: Qt Creatorの基本操作

Qt CreatorはQt開発に特化した強力なIDEです。その主要な画面構成と基本的な使い方を覚えましょう。

3.1 Qt Creatorの画面構成

Qt Creatorを起動すると、以下のような主要なエリアに分かれた画面が表示されます。

  • ようこそ (Welcome) モード: Qt Creator起動時の初期画面です。最近開いたプロジェクト、サンプルプロジェクト、チュートリアル、Qtに関するニュースなどが表示されます。
  • 編集 (Edit) モード: ソースコード(.cpp, .hファイル)、プロジェクトファイル(.pro, CMakeLists.txt)、その他のテキストファイルを編集するためのモードです。強力なコード補完、シンタックスハイライト、コード折りたたみ、リファクタリング機能などを備えています。
  • 設計 (Design) モード: .uiファイル(Qt Designerで作成するUIファイル)を開くと自動的に切り替わります。GUI画面を視覚的に設計するためのモードです。
  • デバッグ (Debug) モード: プログラムを実行し、ブレークポイントを設定したり、変数の値を調べたりしながらデバッグを行うためのモードです。
  • プロジェクト (Projects) モード: プロジェクトの設定(ビルド設定、実行設定など)を行うモードです。使用するKitの選択、ビルドディレクトリの指定、実行時引数などを設定できます。
  • 解析 (Analyze) モード: コード解析ツール(例: Clang-Tidy, Valgrind)の結果を表示するためのモードです。
  • マーケットプレイス (Marketplace) モード: Qt Creatorのプラグインを検索・インストールするためのモードです。

画面左端にはこれらのモードを切り替えるためのアイコンが並んでいます。画面下部には「出力 (Output)」ペインがあり、ビルドの進行状況、エラーメッセージ、アプリケーションの標準出力などが表示されます。

3.2 新しいプロジェクトの作成

Qt Creatorで開発を始めるには、まずプロジェクトを作成します。

  1. Qt Creatorを起動します。
  2. 左端のモード選択アイコンで「ようこそ」モードになっていることを確認します。
  3. 画面中央、またはメニューバーから「ファイル」->「新しいファイルまたはプロジェクト…」を選択します。
  4. 「新しいファイルまたはプロジェクト」ダイアログが表示されます。
  5. 左側のカテゴリツリーから「アプリケーション」->「Qt Widgets Application」を選択します。「Qt Widgets Application」は、デスクトップアプリケーションで一般的なウィンドウベースのGUIを作成するためのテンプレートです。
  6. 「次へ」をクリックします。
  7. プロジェクトの情報の指定:
    • 「名前(N):」:プロジェクトの名前を入力します(例: MyFirstGUI)。
    • 「作成先(C):」:プロジェクトファイルを保存するフォルダを指定します。新しいフォルダを作成しても良いでしょう。
    • 「プロジェクトの場所を追加(A):」:通常は「名前」で指定したプロジェクト名のサブフォルダが作成されます。
    • 「ビルド用にシャドウビルドディレクトリーを使用(S):」:通常はチェックを入れておきます。これにより、ソースコードのあるディレクトリとは別の場所にビルド生成物(実行ファイルなど)が作成され、ソースディレクトリがクリーンに保たれます。
  8. 「次へ」をクリックします。
  9. キットの選択: インストールしたKit(Qtバージョン+コンパイラ)を選択します。通常はデスクトップ用のKit(例: Desktop Qt 6.x.x MinGW 64-bitDesktop Qt 6.x.x MSVC 2019 64-bit)が表示されるので、使用したいものをチェックします。複数のKitを選択することも可能ですが、最初は1つで十分です。
  10. 「次へ」をクリックします。
  11. クラス情報の指定:
    • GUIアプリケーションのメインウィンドウとなるクラスの名前を指定します。デフォルトではMainWindowとなっていますが、変更することも可能です。(例: MyMainWindow
    • ベースクラスとして「QMainWindow」が選択されていることを確認します。QMainWindowは、メニューバー、ツールバー、ステータスバー、中央ウィジェットエリアを持つ標準的なアプリケーションウィンドウのクラスです。
    • 「フォームの作成(F):」:チェックが入っていることを確認します。これにより、Qt Designerで編集できるUIファイル(.ui)が生成されます。
    • 「フォームのファイル名(F):」:デフォルトではmainwindow.uiとなります。
  12. 「次へ」をクリックします。
  13. プロジェクト管理: バージョン管理システム(Gitなど)を使用する場合の設定ですが、最初はスキップして構いません。「完了」をクリックします。

プロジェクトが作成されると、Qt Creatorは自動的に作成されたプロジェクトを開き、「編集」モードに切り替わります。画面左側のプロジェクトツリーには、プロジェクトを構成するファイルが表示されます。

Chapter 4: はじめてのGUIアプリケーション:Hello Qt!

前章で作成した「Qt Widgets Application」プロジェクトは、すでに基本的なGUIアプリケーションとして動作します。まずはそれを実行してみましょう。

4.1 プロジェクトの構成ファイル

Qt Widgets Applicationプロジェクトを作成すると、通常以下の主要なファイルが生成されます。

  • [プロジェクト名].pro: qmakeというビルドシステムのためのプロジェクトファイルです。ソースファイル、ヘッダーファイル、UIファイル、使用するQtモジュールなどが記述されています。
  • main.cpp: アプリケーションのエントリーポイント(main関数)が含まれるファイルです。
  • mainwindow.h: MainWindowクラスのヘッダーファイルです。
  • mainwindow.cpp: MainWindowクラスの実装ファイルです。
  • mainwindow.ui: Qt Designerで設計されたメインウィンドウのUI定義ファイルです。XML形式で記述されています。

4.2 コードを見てみよう (main.cpp)

main.cppファイルを開いてみましょう。

“`cpp

include “mainwindow.h”

include // QApplicationクラスを使うためインクルード

int main(int argc, char *argv[])
{
// QApplicationオブジェクトを作成します。
// GUIアプリケーションは必ずQApplicationのインスタンスを1つ作成する必要があります。
// コマンドライン引数はargc, argvとして渡されます。
QApplication a(argc, argv);

// MainWindowオブジェクトを作成します。
// これがアプリケーションのメインウィンドウになります。
MainWindow w;

// ウィンドウを表示します。
// デフォルトでは非表示になっています。
w.show();

// アプリケーションのイベントループを開始します。
// ここでプログラムの実行が停止し、ユーザーからの入力(マウス、キーボードなど)や
// システムからのイベント(ウィンドウのリサイズなど)を待ち受け、処理します。
// ウィンドウが閉じられるなどの終了イベントが発生すると、exec()は終了し、
// アプリケーションは終了コードを返します。
return a.exec();

}
“`

main関数の中で重要なのは以下の点です。

  • QApplication a(argc, argv);: アプリケーション全体を管理するQApplicationオブジェクトを作成します。GUIアプリケーションには必須です。
  • MainWindow w;: mainwindow.hmainwindow.cppで定義されているMainWindowクラスのインスタンスを作成します。これがGUIウィンドウそのものです。
  • w.show();: 作成したウィンドウを画面に表示します。
  • return a.exec();: アプリケーションのイベントループを開始します。GUIアプリケーションは、ユーザーからの操作などの「イベント」を待ち受け、それに応じて「処理」を行います。exec()関数はこのイベントの待ち受けと処理を継続的に行うためのもので、ウィンドウが閉じられるまでプログラムはこの行で待機します。GUIアプリケーションの心臓部とも言える処理です。

4.3 コードを見てみよう (mainwindow.hmainwindow.cpp)

次に、MainWindowクラスの実装を見てみましょう。

mainwindow.h:

“`cpp

ifndef MAINWINDOW_H

define MAINWINDOW_H

include // QMainWindowを継承するので必要

// UI定義ファイル(mainwindow.ui)から自動生成されるヘッダーファイルをインクルード
// これにより、ui_mainwindow.hの中でMainWindowのUI要素(ウィジェット)にアクセスするための
// uiというメンバ変数が定義されます。
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } // ui_mainwindow.hの中で定義される名前空間とクラス
QT_END_NAMESPACE

// QMainWindowを継承してMainWindowクラスを定義
class MainWindow : public QMainWindow
{
// シグナル&スロット機構など、Qtの拡張機能を使うための必須マクロ
Q_OBJECT

public:
// コンストラクタとデストラクタ
explicit MainWindow(QWidget *parent = nullptr); // explicitは意図しない型変換を防ぐキーワード
~MainWindow();

private:
// ui_mainwindow.hで定義されたUIオブジェクトへのポインタ
// これを通じて、.uiファイルで配置したウィジェットにアクセスします。
Ui::MainWindow *ui;
};

endif // MAINWINDOW_H

“`

  • #include <QMainWindow>: MainWindowQMainWindowを継承しているので必要です。
  • Q_OBJECT: Qtのメタオブジェクトシステム(シグナル/スロット、プロパティなど)を利用するために、QObjectを継承したクラスの定義に記述する必要があるマクロです。
  • namespace Ui { class MainWindow; }: これは前方宣言です。実際の定義はui_mainwindow.hファイルにあります。
  • Ui::MainWindow *ui;: これが重要です。ui_mainwindow.hの中で定義されるUi::MainWindowクラスのインスタンスへのポインタです。このインスタンスを通じて、Qt Designerで配置したウィジェット(例: ボタン、ラベル)にコードからアクセスできるようになります。
  • コンストラクタ MainWindow(QWidget *parent = nullptr);: MainWindowオブジェクトが生成されるときに呼び出されます。
  • デストラクタ ~MainWindow();: MainWindowオブジェクトが破棄されるときに呼び出されます。

mainwindow.cpp:

“`cpp

include “mainwindow.h”

// UI定義ファイルから自動生成されるヘッダーファイルをインクルード
// ここにUi::MainWindowクラスの実装が含まれます。

include “ui_mainwindow.h”

// MainWindowクラスのコンストラクタの実装
// parentは親ウィジェットへのポインタですが、トップレベルウィンドウの場合はnullptrになります。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) // 親クラスQMainWindowのコンストラクタを呼び出し
, ui(new Ui::MainWindow) // Ui::MainWindowオブジェクトをヒープに作成し、uiポインタに設定
{
// Ui::MainWindowオブジェクトの setupUi() メソッドを呼び出します。
// このメソッドが、mainwindow.ui ファイルに記述された内容に基づいて、
// ウィンドウ上にウィジェットを配置し、プロパティを設定します。
ui->setupUi(this);

// ここにカスタムな初期化コードなどを記述できます。
// 例: ウィンドウタイトルを設定
this->setWindowTitle("はじめてのQtウィンドウ");

}

// MainWindowクラスのデストラクタの実装
MainWindow::~MainWindow()
{
// コンストラクタでnewしたUi::MainWindowオブジェクトを解放します。
delete ui;
}
“`

  • #include "ui_mainwindow.h": ビルド時にmainwindow.uiファイルからuicツールによって自動生成されるヘッダーファイルをインクルードしています。
  • コンストラクタ MainWindow::MainWindow(...):
    • : QMainWindow(parent): 親クラスのコンストラクタを呼び出します。
    • : ui(new Ui::MainWindow): Ui::MainWindowクラスのインスタンスを動的に生成し、uiメンバ変数にそのポインタを格納します。
    • ui->setupUi(this);: この行が重要です。 自動生成されたコード(ui_mainwindow.h内で定義されている)に含まれるsetupUi()メソッドを呼び出します。このメソッドが、mainwindow.uiファイルの内容(どのウィジェットをどこに配置するか、ウィジェットの初期プロパティなど)を読み込み、現在のMainWindowインスタンス(this)上にGUIを構築します。
  • デストラクタ MainWindow::~MainWindow(): コンストラクタでnewしたuiオブジェクトをdeleteで解放します。

4.4 アプリケーションのビルドと実行

Qt Creatorでプロジェクトを開いた状態で、画面左下にある実行ボタン(緑色の三角形のアイコン)をクリックします。

  1. ビルド (Build): プロジェクトがまだビルドされていない場合、またはソースコードが変更されている場合、自動的にビルドが開始されます。Qt Creatorはプロジェクト設定(.proファイル)を読み込み、必要なツール(qmake/CMake, moc, uic, rccなど)を呼び出して、C++ソースコードやUIファイルをコンパイル・リンクし、実行ファイルを生成します。ビルドの進行状況やエラーは画面下部の「出力」ペインに表示されます。
  2. 実行 (Run): ビルドが成功すると、生成された実行ファイルが起動します。作成したウィンドウが表示されるはずです。

特に何もウィジェットを配置していない状態では、ただの空のウィンドウが表示されます。しかし、これは紛れもなくQtで作られた最初のGUIアプリケーションです!

ウィンドウが表示されたら、閉じたり、リサイズしたり、最小化したりといった標準的なウィンドウ操作ができることを確認してみてください。

補足:ビルドシステム (qmake と CMake)

Qtプロジェクトのビルドには、主にqmakeとCMakeという2つのビルドシステムが使われます。

  • qmake: Qt専用に設計されたビルドシステムで、シンプルでQtの機能との連携が容易です。.proファイルを使ってプロジェクトを定義します。Qt Creatorで「Qt Widgets Application」などのテンプレートを選ぶと、デフォルトでqmakeプロジェクトが作成されます。
  • CMake: より汎用的なビルドシステムで、Qt以外のC++プロジェクトでも広く使われています。大規模なプロジェクトや、Qt以外のライブラリと連携するプロジェクトでよく選ばれます。CMakeLists.txtファイルを使ってプロジェクトを定義します。Qt 6以降はCMakeが推奨される傾向にあります。

この記事では、Qt Creatorのデフォルトであるqmakeを前提として説明を進めますが、CMakeでも基本的な考え方は同じです。ビルドシステムは、ソースファイルやヘッダーファイル、UIファイルなどを適切にコンパイル・リンクするための指示をまとめる役割を担います。

Chapter 5: Qtの基本構成要素:ウィジェット

GUIアプリケーションは、さまざまなウィジェットの組み合わせで成り立っています。ウィジェットは、ユーザーインターフェース上の個々の要素であり、画面に何かを表示したり、ユーザーからの入力を受け付けたりする役割を担います。Qtには非常に多くの種類のウィジェットが用意されています。

5.1 よく使う基本的なウィジェット

  • QWidget: 全てのウィジェットの基底クラスです。単独で使うことは少ないですが、カスタムウィジェットを作成する際に継承したり、他のウィジェットを配置するためのコンテナとして使ったりします。
  • QMainWindow: メインアプリケーションウィンドウとして使われるクラスです。メニューバー、ツールバー、ステータスバー、ドックウィジェット、そして中央のウィジェットエリアを持つことができます。Chapter 4で作成したアプリケーションのベースクラスでした。
  • QDialog: 短いタスクやユーザーからの入力を求めるための、独立した小さなウィンドウとして使われます。ファイルを開くダイアログ、設定ダイアログなどがこれにあたります。
  • QLabel: テキストや画像を表示するためのウィジェットです。ユーザーからの入力は受け付けません。
  • QPushButton: ユーザーがクリックできるボタンです。最も一般的なウィジェットの一つです。
  • QLineEdit: 1行のテキスト入力フィールドです。ユーザーがキーボードからテキストを入力・編集できます。
  • QTextEdit: 複数行のテキスト入力・表示・編集が可能なウィジェットです。簡単なテキストエディタ機能を提供します。
  • QCheckBox: オン/オフのチェック状態を持つウィジェットです。複数の選択肢から任意数を選択させる場合に使います。
  • QRadioButton: 複数の選択肢から1つだけを選択させるためのウィジェットです。通常、複数のQRadioButtonをグループ化して使用します。
  • QSlider: スライダーを操作して数値を選択するウィジェットです。音量調節などによく使われます。
  • QSpinBox: 上下矢印ボタンを使って数値を増減させるウィジェットです。数値の直接入力も可能です。
  • QComboBox: ドロップダウンリストから項目を選択するウィジェットです。
  • QListWidget: リスト形式で項目を表示し、選択できるウィジェットです。
  • QTableWidget: 表形式でデータを表示・編集できるウィジェットです。

5.2 ウィジェットを配置する方法:コード vs. Qt Designer

ウィジェットをウィンドウ上に配置する方法は、主に2つあります。

  1. コードで手動配置: C++コード内でウィジェットのインスタンスを作成し、親ウィジェットを指定し、位置とサイズを手動で設定する方法です。
    cpp
    // mainwindow.cpp 内のコンストラクタなど
    QLabel *label = new QLabel("Hello, Code!", this); // thisを親ウィジェットに指定
    label->setGeometry(50, 50, 100, 30); // 位置(50,50), サイズ(100x30) を指定

    この方法は、動的にウィジェットを作成・削除する場合や、レイアウトが非常にシンプル・特殊な場合に有効ですが、複雑なUIをコードで全て記述するのは非常に手間がかかりますし、見た目の調整も困難です。

  2. Qt Designerで視覚的に配置: .uiファイルを開き、Qt Designerのキャンバス上にウィジェットをドラッグ&ドロップして配置する方法です。ウィジェットのサイズや位置、プロパティ(表示テキスト、有効/無効など)を視覚的に設定できます。後述するレイアウトと組み合わせて使うのが一般的です。

初心者のうちは、Qt Designerを使ってGUIを設計し、必要に応じてコードからウィジェットのプロパティを操作したり、信号とスロットを接続したりする方法が効率的でおすすめです。Chapter 4で作成したプロジェクトは、最初からmainwindow.uiというUIファイルが含まれているため、Qt Designerを使う準備ができています。

Chapter 6: レイアウト管理

GUI画面の設計において、ウィジェットを単に配置するだけでなく、ウィンドウのサイズが変更されたときにウィジェットの位置やサイズも適切に調整されるようにする必要があります。これを実現するのがレイアウト(Layout)です。

レイアウトを使用しない場合、ウィジェットは指定された固定位置に配置されます。ウィンドウのサイズを変更してもウィジェットの位置やサイズは変わりません。これでは、ウィンドウが大きくなっても余白が増えるだけであったり、小さくするとウィジェットが隠れてしまったりします。

レイアウトを使用すると、ウィジェットは特定のルールに従って配置され、ウィンドウのサイズ変更に応じて自動的に位置やサイズが調整されます。これにより、様々な画面サイズや解像度に対応できる柔軟なUIを作成できます。

6.1 主なレイアウトクラス

Qtにはいくつかの標準的なレイアウトクラスがあります。

  • QHBoxLayout: ウィジェットを水平方向(左から右へ)に一列に並べます。
  • QVBoxLayout: ウィジェットを垂直方向(上から下へ)に一列に並べます。
  • QGridLayout: ウィジェットをグリッド(行と列)に配置します。表形式のUIを作るのに便利です。
  • QFormLayout: ラベルと入力フィールドのペアを並べるのに特化したレイアウトです。設定画面などでよく使われます。

これらのレイアウトは、単独で使うだけでなく、組み合わせて使うこともできます。例えば、垂直レイアウトの中に複数の水平レイアウトを配置することで、より複雑なUI構造を作成できます。

6.2 Qt Designerでのレイアウトの使用

Qt Designerを使うと、レイアウト管理も視覚的に行えます。

  1. Qt Creatorでmainwindow.uiファイルを開きます。すると「設計」モードに切り替わります。
  2. 画面左上の「Widget Box」ペインには、利用可能なウィジェットやレイアウトが表示されています。
  3. 画面中央の「キャンバス」エリアに、いくつかウィジェット(例: QLabelQPushButton)をドラッグ&ドロップで配置してみましょう。この状態では、ウィジェットは自由に動かせますが、レイアウトはまだ設定されていません。
  4. レイアウトを設定したいウィジェット全体を選択します。複数のウィジェットを選択するには、キャンバス上でドラッグして範囲選択するか、Ctrlキー(macOSではCommandキー)を押しながらクリックします。あるいは、画面右上の「Object Inspector」ペインで、レイアウトを適用したい親ウィジェット(通常はMainWindowの中央ウィジェット)を選択します。
  5. ウィジェットまたは親ウィジェットを選択した状態で、Qt Creatorのツールバーにあるレイアウト関連のアイコンをクリックします。アイコンは通常、グリッド状のボタンとして表示され、マウスオーバーすると「Lay Out Horizontally (in a QHBoxLayout)」、「Lay Out Vertically (in a QVBoxLayout)」、「Lay Out in a Grid (in a QGridLayout)」などの説明が表示されます。
  6. 例えば、「Lay Out Vertically」アイコンをクリックしてみましょう。選択していたウィジェットが垂直方向に整列され、親ウィジェット全体を覆うように配置されます。Object Inspectorを見ると、親ウィジェットの下にQVBoxLayoutという項目が追加され、その下にウィジェットが配置されていることが分かります。
  7. レイアウトを設定した後、ウィンドウのリサイズハンドルをドラッグしてウィンドウサイズを変更してみてください。ウィジェットがレイアウトのルールに従って自動的にサイズや位置を調整するのが確認できるはずです。
  8. スペーサー (Spacer): レイアウト内に固定または伸縮する空白を追加したい場合は、「Widget Box」にある「Horizontal Spacer」や「Vertical Spacer」をレイアウトにドラッグ&ドロップします。これは、ウィジェットをレイアウトの一端に寄せたい場合などに便利です。

6.3 レイアウトの重要性

レイアウトはGUIプログラミングにおいて非常に重要です。

  • ウィンドウサイズへの対応: 様々なモニターサイズやウィンドウサイズでアプリケーションが正しく表示されるようにします。
  • ローカライゼーション: UIテキストの長さが言語によって変わっても、ウィジェットのサイズや位置が自動的に調整され、レイアウトが崩れにくくなります。
  • 保守性: コードで座標をハードコードするよりも、レイアウトで構造的に配置する方が、後からUIを変更する際に修正が容易になります。

Qt Designerでレイアウトを適切に設定することで、コード量を減らしつつ、保守性の高いUIを効率的に作成できます。

Chapter 7: シグナル&スロット

Qtの最も特徴的で強力な機能の一つが、シグナル&スロット(Signal & Slot)機構です。これは、オブジェクト間の通信やイベント処理を行うためのメカニズムです。

7.1 シグナル&スロットの概念

従来のイベント処理では、イベント発生元(例: ボタン)がイベントハンドラ関数を直接呼び出すか、あるいはコールバック関数を登録するのが一般的でした。しかし、これだとイベント発生元がイベントハンドラの実装を知っている必要があり、オブジェクト間の結合度が高くなります。

シグナル&スロット機構では、この問題を解決します。

  • シグナル (Signal): あるオブジェクトで特定の「イベント」が発生したときに「発信」されるものです。例えば、QPushButtonがクリックされたときに発信されるclicked()シグナルなどがあります。シグナルは、そのシグナルを受け取る側のオブジェクト(受信者)や、どのようなスロット(処理関数)が接続されているかを知りません。ただ「イベントが発生した」という事実を通知するだけです。
  • スロット (Slot): シグナルを受信したときに実行される「処理」を行う関数です。任意数のシグナルを1つのスロットに接続したり、1つのシグナルを複数のスロットに接続したりすることができます。スロットは通常のメンバ関数と同じように定義されます。

シグナルとスロットは、互いに直接呼び出すのではなく、Qtのメタオブジェクトシステムを通じて「接続 (connect)」されます。これにより、イベント発生元と処理を行う側のオブジェクトは互いの詳細を知る必要がなくなり、疎結合な設計が可能になります。

7.2 シグナルとスロットの接続(コード編)

シグナルとスロットを接続するには、静的メンバ関数であるQObject::connect()関数を使用します。

QObject::connect(sender, signal, receiver, slot)

  • sender: シグナルを発信するオブジェクトのポインタ。
  • signal: 発信するシグナル。Qt 5以降では、メンバ関数ポインタ構文 &SenderClass::signalName を使うのが一般的です。Qt 4以前は SIGNAL(signalName()) というマクロを使いました。
  • receiver: シグナルを受信するオブジェクトのポインタ。
  • slot: 受信側で実行するスロット(関数)。こちらもメンバ関数ポインタ構文 &ReceiverClass::slotName またはマクロ SLOT(slotName()) を使います。

例:ボタンがクリックされたらウィンドウを閉じる

“`cpp
// mainwindow.cpp 内のコンストラクタ
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);

// PushButtonを例とする
QPushButton *closeButton = new QPushButton("閉じる", this);
closeButton->setGeometry(100, 100, 80, 30);

// closeButtonのclicked()シグナルを、このMainWindowオブジェクトのclose()スロットに接続
// close()はQWidget(QMainWindowの基底クラス)に定義されている標準スロット
connect(closeButton, &QPushButton::clicked, this, &MainWindow::close);

// またはQt 4以前のマクロ構文 (非推奨だが古いコードで見かける)
// connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));

}
“`

シグナルとスロットの引数:

シグナルとスロットは引数を持つことができます。シグナルからスロットへ値を渡すことが可能です。接続するためには、シグナルとスロットの引数の数と型が一致しているか、シグナルの引数がスロットの引数よりも多い場合に、シグナルの先頭の引数から順にスロットの引数と型が一致している必要があります(余分なシグナルの引数は無視されます)。

例:Sliderの値が変更されたらLabelに表示する

QSlidervalueChanged(int)シグナルを、QLabelsetNum(int)スロットに接続する場合。

“`cpp
// mainwindow.cpp 内のコンストラクタ
QSlider *slider = new QSlider(Qt::Horizontal, this);
slider->setGeometry(50, 150, 200, 30);
slider->setRange(0, 100);

QLabel *valueLabel = new QLabel(“0”, this);
valueLabel->setGeometry(260, 150, 50, 30);

// sliderのvalueChanged(int)シグナルを valueLabelのsetNum(int)スロットに接続
// シグナルとスロットは引数1つ (int) で一致
connect(slider, &QSlider::valueChanged, valueLabel, &QLabel::setNum);
“`

C++11以降のLambda関数を使った接続:

現代のC++では、スロットとしてラムダ関数を使うことも非常に一般的です。これは、特に簡単な処理をその場で記述したい場合に便利です。

“`cpp
// mainwindow.cpp 内のコンストラクタ
QPushButton *greetButton = new QPushButton(“挨拶”, this);
greetButton->setGeometry(50, 200, 80, 30);

QLabel *messageLabel = new QLabel(“ここにメッセージが表示されます”, this);
messageLabel->setGeometry(140, 200, 200, 30);

// greetButtonのclicked()シグナルをラムダ関数に接続
// ラムダ関数内でmessageLabelのテキストを変更
connect(greetButton, &QPushButton::clicked, this,
= { // [=] は外部の変数を値でキャプチャ (ここではmessageLabelなど)
messageLabel->setText(“こんにちは、Qt!”);
});
“`

ラムダ関数を使う場合、thisをレシーバーとして指定するのが一般的です。また、ラムダ関数内でクラスのメンバ変数(例: ui->label)にアクセスする場合は、ラムダ関数のキャプチャリストにthisを含める必要があります。

7.3 シグナルとスロットの接続(Qt Designer編)

Qt Designerを使うと、コードを書かずにシグナルとスロットを視覚的に接続することも可能です。特に、ウィジェットの標準シグナルを、他のウィジェットの標準スロットに接続する場合や、カスタムクラスのパブリックスロットに接続する場合に便利です。

  1. Qt Creatorでmainwindow.uiファイルを開き、「設計」モードにします。
  2. 画面右上の「Object Inspector」の下にある「Signals & Slots Editor」タブを選択します。
  3. 「+」ボタンをクリックして新しい接続を追加します。
  4. 新しい接続行が追加されます。「Sender」列のドロップダウンリストからシグナルを発信するウィジェットを選択します(例: pushButton)。
  5. 「Signal」列のドロップダウンリストから発信ウィジェットが持つシグナルを選択します(例: clicked())。
  6. 「Receiver」列のドロップダウンリストからシグナルを受信するウィジェットを選択します(例: label)。
  7. 「Slot」列のドロップダウンリストから受信ウィジェットが持つスロットを選択します(例: setText(QString) – これはQLabelの標準スロットではありませんが、他のウィジェットのスロットを選択できます)。カスタムスロットを選択するには、事前にヘッダーファイルでそのスロットをpublic slots:セクションに宣言しておく必要があります。
  8. 選択が完了すると、シグナルとスロットが接続されます。

この方法で接続した場合、ビルド時にuicツールが生成するui_mainwindow.hファイル内のsetupUi()関数の中に、connect()関数の呼び出しが自動的に記述されます。

7.4 カスタムシグナルとカスタムスロット

独自のクラスでイベントを定義したり、特定の処理をスロットとして公開したりすることも可能です。

  • カスタムシグナル: .hファイルのクラス定義内のsignals:セクションに、戻り値の型がなく、引数を持つことができる関数プロトタイプとして宣言します。実装は書きません。シグナルを発信したい箇所で、emit signalName(arguments); という構文で呼び出します。emitキーワードはQt独自の拡張ですが、実際には何もせず、単にその後の関数呼び出しをコンパイラに伝える役割を果たします。
  • カスタムスロット: .hファイルのクラス定義内のpublic slots:protected slots:、またはprivate slots:セクションに通常のメンバ関数として宣言します。.cppファイルにその実装を記述します。public slots:に定義されたスロットはQt Designerからも接続可能になります。

例:カスタムボタンクラスで独自のシグナルを定義

“`cpp
// mybutton.h

ifndef MYBUTTON_H

define MYBUTTON_H

include

class MyButton : public QPushButton
{
Q_OBJECT // Q_OBJECTマクロは必須

public:
MyButton(QWidget *parent = nullptr);

signals: // カスタムシグナルの定義
// このボタンがクリックされたときに、特定の文字列と共に発信されるシグナル
void messageClicked(const QString &message);

// public slots: // 必要であればカスタムスロットを定義

protected:
// マウスクリックイベントを補足してシグナルを発信する例
void mousePressEvent(QMouseEvent *event) override;
};

endif // MYBUTTON_BUTTON_H

// mybutton.cpp

include “mybutton.h”

include

include // デバッグ出力用

MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{
// ボタンのテキストなどを設定
setText(“Click Me (Custom)”);
}

// mousePressEventをオーバーライドして、クリックされたらmessageClickedシグナルを発信
void MyButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
qDebug() << “Custom button clicked, emitting signal.”;
// messageClickedシグナルを発信。引数として文字列を渡す。
emit messageClicked(“Hello from MyButton!”);
}
// 元のmousePressEventの処理も呼び出す(ボタンの状態変更など)
QPushButton::mousePressEvent(event);
}

// mainwindow.cpp のコンストラクタでMyButtonとLabelを使い、シグナルを接続する例
// (MyButtonは別途プロジェクトに追加し、インクルードする必要があります)

include “mybutton.h” // MyButtonをインクルード

// … MainWindow::MainWindow(…)
// MyButtonのインスタンスを作成
MyButton *customButton = new MyButton(this);
customButton->setGeometry(50, 250, 150, 30);

QLabel *statusLabel = new QLabel(“Waiting for custom button click…”, this);
statusLabel->setGeometry(210, 250, 300, 30);

// MyButtonのmessageClicked(const QString&)シグナルを、statusLabelのsetText(const QString&)スロットに接続
// シグナルとスロットは引数1つ (QString) で一致
connect(customButton, &MyButton::messageClicked, statusLabel, &QLabel::setText);

“`
このように、シグナル&スロット機構を使うことで、様々なオブジェクト間で発生するイベントとそれに対する処理を、柔軟かつ疎結合な方法で結びつけることができます。これはQtプログラミングの根幹をなす非常に重要な概念です。

Chapter 8: Qt Designerの活用

Chapter 5と6で触れたように、Qt DesignerはGUI設計において非常に強力なツールです。ここでは、Qt Designerの画面構成や主要な機能、そしてUIファイル(.ui)がどのようにコードと連携するのかを詳しく見ていきます。

8.1 Qt Designerの画面構成

Qt Creatorで.uiファイルを開くと、Qt Designerの画面(設計モード)に切り替わります。主な要素は以下の通りです。

  • Widget Box (ウィジェットボックス): 画面左側にあります。利用可能なウィジェット、レイアウト、スペーサーなどがリストされています。ここからキャンバスへドラッグ&ドロップしてUI要素を配置します。カテゴリ分けされており、目的のウィジェットを見つけやすくなっています。
  • キャンバス (Canvas): 画面中央の大きな領域です。ここにウィジェットを配置し、レイアウトを設定し、UIの見た目を設計します。選択したウィジェットはドラッグして移動したり、ハンドルを使ってサイズを変更したりできます。
  • Object Inspector (オブジェクトインスペクター): 画面右上にあります。現在のUIフォーム上の全てのオブジェクト(ウィジェットやレイアウト)をツリー構造で表示します。オブジェクトの親子関係や階層構造を確認できます。ここから特定のウィジェットを選択してプロパティを編集したり、レイアウト構造を確認したりできます。ウィジェットのオブジェクト名(objectName)は、コードからそのウィジェットを参照する際に使う重要な識別子です。
  • Property Editor (プロパティエディター): Object Inspectorの下にあります。Object Inspectorで選択したウィジェットの様々なプロパティ(例: ウィジェットのテキスト、サイズ、色、有効/無効状態など)を表示・編集できます。プロパティはカテゴリ分けされており、検索も可能です。
  • Signals & Slots Editor (シグナル&スロットエディター): Object InspectorやProperty Editorの隣にあるタブとして表示されます(見つからない場合はメニューバーの「ツール」->「フォームエディター」->「シグナル/スロットエディター」などで表示できます)。ここでシグナルとスロットの接続を視覚的に設定できます。
  • Action Editor (アクションエディター): メニューバーやツールバーに表示する「アクション」(例: 「ファイルを開く」「コピー」など、ユーザーが実行できる特定の操作)を管理します。
  • Resource Editor (リソースエディター): アプリケーションで使用する画像ファイルやアイコンなどのリソースファイルを管理します。これらのファイルは実行ファイルに埋め込むことができます。

8.2 GUIの設計手順例

Qt Designerを使ったGUI設計の一般的な手順は以下の通りです。

  1. ウィジェットの配置: Widget Boxから必要なウィジェット(QLabel, QLineEdit, QPushButtonなど)をキャンバスにドラッグ&ドロップします。
  2. オブジェクト名の設定: Object Inspectorで各ウィジェットを選択し、Property Editorの上部にあるobjectNameプロパティを分かりやすい名前に変更します(例: labelMessage, lineEditInput, buttonOK)。この名前をコードからウィジェットにアクセスする際に使用します。
  3. プロパティの設定: Property Editorを使って、各ウィジェットの初期状態を設定します(例: QLabelの表示テキスト、QPushButtonのボタンテキスト、QLineEditのプレースホルダーテキスト、ウィジェットの有効/無効など)。
  4. レイアウトの設定: ウィジェットを適切に配置し、複数のウィジェットを選択してツールバーのレイアウトボタンをクリックするか、Object Inspectorで親ウィジェットを選択して右クリックメニューから「レイアウト」を選択して、レイアウト(QVBoxLayout, QHBoxLayout, QGridLayoutなど)を適用します。レイアウト内にウィジェットをドラッグ&ドロップしたり、スペーサーを追加したりして、意図した配置になるように調整します。レイアウト内でウィジェットのサイズポリシー(拡大縮小の挙動)をProperty EditorのsizePolicyプロパティで調整することも重要です。
  5. シグナルとスロットの接続 (オプション): Signals & Slots Editorを使って、ウィジェット間の基本的な相互作用を設定します(例: ボタンクリックで何かを表示/非表示にする)。
  6. 保存: .uiファイルを保存します。

8.3 .uiファイルとuicツール

Qt Designerで作成した.uiファイルは、人間が読めるXML形式のテキストファイルです。このファイル自体は実行可能なコードではありません。Qtのビルドシステムは、この.uiファイルを読み込み、uic(User Interface Compiler)というツールを使って、対応するC++ヘッダーファイル(通常 ui_[フォームファイル名].h という名前、例: ui_mainwindow.h)を自動生成します。

この自動生成されたヘッダーファイルには、.uiファイルで定義されたウィジェットを作成し、プロパティを設定し、レイアウトに配置するためのC++コードが記述されています。

例えば、mainwindow.uiがあり、そこにQLabelQPushButtonが配置されている場合、uicによって生成されるui_mainwindow.hには、以下のようなクラス定義が含まれます(簡略化しています)。

“`cpp
// ui_mainwindow.h (uic によって自動生成されるファイル)

ifndef UI_MAINWINDOW_H

define UI_MAINWINDOW_H

include

include

include

include

include

include

include

include

include

QT_BEGIN_NAMESPACE

class Ui_MainWindow
{
public:
QWidget centralwidget;
QVBoxLayout
verticalLayout; // レイアウト
QLabel label; // .uiで配置したQLabel
QPushButton
pushButton; // .uiで配置したQPushButton
QMenuBar menubar;
QStatusBar
statusbar;

// UIを構築するメソッド
void setupUi(QMainWindow *MainWindow)
{
    if (MainWindow->objectName().isEmpty())
        MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
    MainWindow->resize(800, 600); // .uiで設定したサイズ

    centralwidget = new QWidget(MainWindow);
    centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
    verticalLayout = new QVBoxLayout(centralwidget);
    verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));

    label = new QLabel(centralwidget); // QLabelを作成
    label->setObjectName(QString::fromUtf8("label")); // オブジェクト名を設定
    label->setText(QCoreApplication::translate("MainWindow", "Hello, Designer!", nullptr)); // テキストを設定

    verticalLayout->addWidget(label); // レイアウトに追加

    pushButton = new QPushButton(centralwidget); // QPushButtonを作成
    pushButton->setObjectName(QString::fromUtf8("pushButton")); // オブジェクト名を設定
    pushButton->setText(QCoreApplication::translate("MainWindow", "Click Me", nullptr)); // テキストを設定

    verticalLayout->addWidget(pushButton); // レイアウトに追加

    MainWindow->setCentralWidget(centralwidget); // 中央ウィジェットとして設定
    // ... メニューバーやステータスバーの設定 ...
} // setupUi

// 後片付けを行うメソッド
void retranslateUi(QMainWindow *MainWindow)
{
    // ... テキストの再設定など(主に国際化対応用) ...
} // retranslateUi

};

namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

endif // UI_MAINWINDOW_H

“`

そして、あなたのmainwindow.cppのコンストラクタで呼び出している ui->setupUi(this); は、この自動生成されたUi_MainWindow::setupUi関数を呼び出しています。この関数が実行されることで、.uiファイルで設計した通りのUIがウィンドウ上に構築されるのです。

コードからQt Designerで配置したウィジェットにアクセスしたい場合は、uiメンバ変数を通じてアクセスします。例えば、objectNamelabelMessageQLabelのテキストを変更したい場合は、ui->labelMessage->setText("新しいテキスト");のように記述します。

Qt Designerを効果的に活用することで、GUI設計の効率を大幅に向上させることができます。見た目の調整はDesignerで行い、ウィジェットの操作やイベント処理といったロジックはC++コードで記述するという役割分担が、QtでのGUI開発の基本的なスタイルです。

Chapter 9: 簡単なインタラクティブアプリケーションの作成

これまでに学んだウィジェット、レイアウト、シグナル&スロット、そしてQt Designerの知識を使って、実際にユーザー操作に反応する簡単なアプリケーションを作成してみましょう。

例として、「テキストを入力し、ボタンをクリックすると、入力されたテキストを別のラベルに表示する」というアプリケーションを作成します。

9.1 プロジェクトの作成とUI設計

  1. Qt Creatorで新しい「Qt Widgets Application」プロジェクトを作成します(Chapter 4参照)。プロジェクト名は例えばTextDisplayAppとします。メインウィンドウクラスはMainWindow、UIファイルはmainwindow.uiのまま進めます。
  2. プロジェクト作成後、左側のプロジェクトツリーからFormsフォルダを展開し、mainwindow.uiファイルをダブルクリックしてQt Designerを開きます。
  3. ウィジェットの配置:
    • Widget BoxからQLabelをキャンバスにドラッグ&ドロップします。テキストを「入力してください:」とでも設定します。
    • Widget BoxからQLineEditをドラッグ&ドロップします。
    • Widget BoxからQPushButtonをドラッグ&ドロップします。テキストを「表示」とでも設定します。
    • Widget Boxからもう一つQLabelをドラッグ&ドロップします。ここにQLineEditに入力されたテキストを表示します。初期テキストは空にしておくか、「ここに表示されます」などとしておきます。
  4. オブジェクト名の変更:
    • QLineEditを選択し、Object InspectorでobjectNamelineEditInputに変更します。
    • QPushButtonを選択し、objectNamepushButtonDisplayに変更します。
    • 結果を表示するQLabelを選択し、objectNamelabelResultに変更します。
    • 最初のQLabel(「入力してください:」)はコードから参照する必要がなければ、オブジェクト名はデフォルトのままでも構いません(例: label)。
  5. レイアウトの設定:
    • キャンバス上の全てのウィジェットを選択します。
    • ツールバーのレイアウトボタン(例: 垂直レイアウト QVBoxLayout)をクリックしてレイアウトを適用します。
    • (オプション)最初のQLabelとQLineEditを横並びにしたい場合は、この2つだけを選択してQHBoxLayoutを適用し、そのQHBoxLayout全体を他のウィジェットと一緒にQVBoxLayoutに含めるように調整します。Qt DesignerのObject Inspector上でレイアウト構造を確認しながらドラッグ&ドロップで階層構造を変更できます。
    • レイアウトを適用したら、ウィンドウサイズを変更してみて、ウィジェットの配置が崩れないか確認します。必要に応じてProperty Editorで各ウィジェットのsizePolicyなどを調整します。
  6. UIファイルの保存: ファイルを保存します(Ctrl+S または Command+S)。

9.2 シグナルとスロットの接続(コード編)

このアプリケーションでは、「表示」ボタンがクリックされたら、QLineEditのテキストを取得し、QLabelに設定するという処理を行います。これをシグナル&スロットで実現します。QPushButtonのclicked()シグナルを、MainWindowクラスに新しく定義するカスタムスロットに接続します。

  1. カスタムスロットの宣言:

    • プロジェクトツリーからHeadersフォルダを展開し、mainwindow.hファイルをダブルクリックして開きます。
    • MainWindowクラスの定義の中で、private:セクションの下にprivate slots:セクションを追加し、カスタムスロット関数を宣言します。Qt DesignerでQPushButtonのobjectNamepushButtonDisplayとした場合、on_pushButtonDisplay_clicked()という名前のスロットを定義しておくと、Qtの自動接続機能(Auto-connection)が働いて、明示的なconnect()呼び出しなしでシグナルとスロットが接続されます。ただし、ここではconnect()関数を使った明示的な接続も理解するために、別の名前で定義してみましょう。
      “`cpp
      // mainwindow.h (MainWindow クラス定義内)
      // …
      private:
      Ui::MainWindow *ui;

    private slots: // ここにカスタムスロットを宣言
    void handleDisplayButtonClick(); // ボタンクリック時に実行するスロット

    // …
    ``private slots:` にすることで、このスロットはクラス外から直接呼び出されることはなく、シグナルからのみ呼び出されるようになります。

  2. カスタムスロットの実装:

    • プロジェクトツリーからSourcesフォルダを展開し、mainwindow.cppファイルをダブルクリックして開きます。
    • MainWindowクラスの実装内で、handleDisplayButtonClick()スロットの実装を記述します。
      “`cpp
      // mainwindow.cpp (MainWindow クラス実装内)
      // …

    // カスタムスロットの実装
    void MainWindow::handleDisplayButtonClick()
    {
    // 1. QLineEdit (objectName: lineEditInput) からテキストを取得
    QString inputText = ui->lineEditInput->text();

    // 2. QLabel (objectName: labelResult) にテキストを設定
    ui->labelResult->setText("入力されたテキスト: " + inputText);
    
    // (オプション)QLineEdit の内容をクリアする場合
    // ui->lineEditInput->clear();
    

    }

    // …
    ``ui->lineEditInputui->labelResultは、mainwindow.hで宣言したuiポインタを通じて、Qt Designerで配置したウィジェット(それぞれのobjectNameで識別される)にアクセスしています。QLineEditの現在のテキストを取得するにはtext()メソッドを、QLabelのテキストを設定するにはsetText()`メソッドを使用します。

  3. シグナルとスロットの接続:

    • mainwindow.cppMainWindow コンストラクタ内で、シグナルとスロットを接続します。
      “`cpp
      // mainwindow.cpp (MainWindow コンストラクタ内)
      MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
      {
      ui->setupUi(this);

      // QPushButton (objectName: pushButtonDisplay) の clicked() シグナルを、
      // この MainWindow オブジェクトの handleDisplayButtonClick() スロットに接続
      connect(ui->pushButtonDisplay, &QPushButton::clicked,
      this, &MainWindow::handleDisplayButtonClick);

      // (オプション)ウィンドウタイトルを設定
      setWindowTitle(“テキスト表示アプリ”);
      }
      // …
      ``
      ここで使用している
      connect()`関数は、Chapter 7で説明したメンバ関数ポインタ構文です。

9.3 アプリケーションのビルドと実行

  1. Qt Creatorの左下にある緑色の実行ボタンをクリックします。
  2. プロジェクトがビルドされ、成功すればアプリケーションが起動します。
  3. 表示されたウィンドウのテキストフィールドに何かテキストを入力します。
  4. 「表示」ボタンをクリックします。
  5. ボタンの下のラベルに、入力したテキストが表示されれば成功です!

この簡単なアプリケーションを通して、UI設計(Qt Designer)、ウィジェットの操作(コード)、そしてユーザー操作への反応(シグナル&スロット)というGUIアプリケーション開発の基本的な流れを体験できました。

Chapter 10: ビルドと実行の詳細

これまでのステップで、Qt Creatorの実行ボタン一つでビルドから実行までが行われましたが、その裏側で何が起こっているのかを少し掘り下げて理解することは重要です。特に、Qt特有のツールであるmocuicの役割を知っておきましょう。

10.1 ビルドプロセス

Qtプロジェクトのビルドは、一般的に以下のステップで行われます。

  1. ビルドシステムの実行 (qmake または CMake): プロジェクトファイル(.pro または CMakeLists.txt)を読み込み、ソースコード、ヘッダーファイル、UIファイル、リソースファイルなどを特定し、それらをコンパイルするためのMakefile(またはNinjaビルドファイルなど)を生成します。
  2. moc (Meta-Object Compiler) の実行: Q_OBJECTマクロが記述されたC++ヘッダーファイル(例: mainwindow.h)を解析し、Qtのメタオブジェクトシステム(シグナル/スロット、プロパティなど)を実装するための追加のC++コード(通常 moc_[ファイル名].cpp という名前)を生成します。シグナル&スロット機構がC++の標準機能の範囲を超えているため、このmocによる前処理が必要です。
  3. uic (User Interface Compiler) の実行: Qt Designerで作成した.uiファイル(XML形式)を読み込み、UIを構築するためのC++ヘッダーファイル(通常 ui_[ファイル名].h という名前、例: ui_mainwindow.h)を生成します。Chapter 8で説明した通り、このファイルにはsetupUi()関数などが含まれます。
  4. rcc (Resource Compiler) の実行: .qrcファイル(リソースファイルリスト)を読み込み、アプリケーションで使用する画像ファイルやアイコンなどを実行ファイルに埋め込むためのC++コード(通常 qrc_[ファイル名].cpp という名前)を生成します。これにより、外部ファイルに依存せず、単一の実行ファイルでリソースを扱えるようになります。
  5. C++コンパイラとリンカの実行: 生成されたmoc_*.cppui_*.hqrc_*.cppファイルと、あなたが書いたC++ソースファイル(.cpp)をまとめて、C++コンパイラ(GCC, Clang, MSVCなど)がオブジェクトファイルにコンパイルします。最後に、これらのオブジェクトファイルと必要なQtライブラリをリンカが結合し、実行ファイルを生成します。

Qt Creatorの「ビルド」ボタンをクリックすると、これらのステップが適切な順序で自動的に実行されます。画面下部の「出力」ペインにある「ビルド出力」タブを見ると、各ステップで実行されているコマンドを確認できます。

10.2 デバッグビルドとリリースビルド

Qt Creatorでビルドを行う際、通常は「Debug」または「Release」というビルドコンフィグレーションを選択できます。画面左下の実行ボタンの隣にあるドロップダウンリストで切り替え可能です。

  • Debugビルド: デバッグ用の情報(シンボル情報など)が含まれたビルドです。最適化は控えめ、または行われません。実行速度は遅いですが、Qt Creatorのデバッガを使ってプログラムの実行を一時停止したり、変数の値を調べたり、ステップ実行したりするのに適しています。開発中にバグを見つけるために使用します。
  • Releaseビルド: 最適化が最大限に行われたビルドです。デバッグ情報は通常含まれません。実行速度は速く、ファイルサイズも小さくなります。ユーザーに配布するための最終的なアプリケーションをビルドする際に使用します。Releaseビルドでビルドしたアプリケーションはデバッガで詳細なステップ実行をすることが難しいです。

開発中はDebugビルドで、完成したらReleaseビルドで最終確認を行うのが一般的なワークフローです。

10.3 実行ファイルの場所

Qt Creatorでビルドした実行ファイルは、プロジェクトフォルダのサブフォルダに生成されます。デフォルトでは、プロジェクトフォルダの下にビルドコンフィグレーション名(例: build-MyFirstGUI-Desktop_Qt_...-Debugbuild-MyFirstGUI-Desktop_Qt_...-Release)のフォルダが作成され、その中に実行ファイル(Windowsでは.exe、macOSでは.appバンドル、Linuxでは実行権限が付与されたファイル)が格納されます。

アプリケーションを他のコンピュータで実行したい場合は、この実行ファイルだけでなく、アプリケーションが依存しているQtの共有ライブラリ(.dll, .dylib, .so ファイルなど)も一緒に配布する必要があります。これを「デプロイメント」と呼び、Qtにはwindeployqt (Windows), macdeployqt (macOS), linuxdeployqt (Linux) といったデプロイメントツールが用意されています。デプロイメントは初心者にとっては少し複雑なトピックなので、まずは自分の開発環境で実行できることを目標にしましょう。

Chapter 11: さらなるステップへ

Qt入門の第一歩として、GUIプログラミングの基本的な流れと主要な要素を学びました。しかし、Qtは非常に広範な機能を持つフレームワークです。ここからさらに学習を進めるための方向性をいくつか紹介します。

11.1 より高度なウィジェットとUIパターン

  • QDialog: モーダル/非モーダルダイアログの作成と使い方。ファイルダイアログ、色選択ダイアログなどの標準ダイアログの利用。
  • Model/Viewプログラミング: QListView, QTreeView, QTableViewなどのビュークラスと、データを管理するモデルクラス(QStringListModel, QStandardItemModelなど)を組み合わせて、大量のデータを効率的に表示・操作する方法。Qtの強力な機能の一つです。
  • カスタムウィジェット: 既存のウィジェットでは実現できない独自の見た目や振る舞いを持つウィジェットを、QWidgetや他のウィジェットを継承して作成する方法。
  • Qt Quick (QML): これまで学んだのは「Qt Widgets」というUIモジュールですが、Qtには「Qt Quick」という別のUI技術もあります。これはQMLという宣言的な言語を使ってUIを記述し、ハードウェアアクセラレーションを活用して滑らかなアニメーションやリッチなUIを作成するのに適しています。特にモバイルや組み込み開発で人気がありますが、デスクトップでも利用されます。Widgetsとは思想やアプローチが異なるため、別途学習が必要です。

11.2 その他のQtモジュール

QtはGUIだけでなく、様々な機能を提供するモジュールの集まりです。

  • Qt Network: HTTP, FTP, TCP/IPなどのネットワーク通信を扱うモジュール。
  • Qt SQL: データベース(SQLite, MySQL, PostgreSQLなど)にアクセスするためのモジュール。
  • Qt Multimedia: 音声や動画の再生、録音、カメラアクセスなどを扱うモジュール。
  • Qt Graphics/Rendering: QPainterを使った2Dグラフィックス描画、OpenGL/Vulkanを使った3Dグラフィックス描画。
  • Qt Core: GUIに依存しない、基本的なデータ構造(QString, QList, QMapなど)、ファイルI/O、スレッド、イベントループ、タイマーなどの機能を提供するモジュール。

11.3 学習リソース

  • Qt公式ドキュメント (Qt Documentation): 最も正確で詳細な情報源です。各クラスや関数のリファレンス、チュートリアル、例が含まれています。Qt Creatorのヘルプモードからもアクセスできます(F1キーでカーソル下のクラスや関数に関するヘルプを表示)。
  • Qt Examples: Qtのインストールに含まれているか、Qt Creatorの「ようこそ」モードからアクセスできるサンプルプロジェクトです。様々なQtの機能の使い方を実際のコードで学ぶのに非常に役立ちます。
  • Qt Wiki: Qtコミュニティが作成した様々な情報が集まっています。
  • 書籍、オンラインコース: Qtに関する多くの書籍やUdemy, Courseraなどのオンライン学習プラットフォームのコースがあります。
  • Qt Forum / Stack Overflow: 疑問点や問題に直面した際に、他の開発者に質問したり、既存の回答を探したりできるコミュニティサイトです。

11.4 学習の進め方のヒント

  • 実際にコードを書く: チュートリアルを読むだけでなく、手を動かしてコードを書き、自分で小さなアプリケーションを作成することが最も重要です。
  • 既存のサンプルコードを読む: Qtのサンプルコードは非常に質が高いです。動かしてみて、コードを読んで、どのように書かれているかを理解しましょう。
  • 公式ドキュメントを参照する習慣をつける: 分からないクラスや関数が出てきたら、まずは公式ドキュメントで調べる癖をつけましょう。
  • 小さなプロジェクトから始める: 最初から大規模なアプリケーションを作ろうとせず、今回のような簡単なアプリから始めて、徐々に機能を拡張したり、新しいウィジェットやモジュールを使ったりしていくのが良いでしょう。
  • エラーメッセージを恐れない: ビルドエラーや実行時エラーはつきものです。エラーメッセージをよく読み、Qt Creatorの「出力」ペインやデバッガを活用して原因を特定し、解決策を探しましょう。

結論

本記事では、Qtを使った初心者向けGUIプログラミングの第一歩として、Qtの概要、開発環境の構築、Qt Creatorの基本操作、そして最初の「Hello Qt」アプリケーションの作成から、ウィジェット、レイアウト、シグナル&スロットといったQtの基本的な構成要素について詳しく解説しました。さらに、Qt Designerの活用法や、ビルドプロセス、今後の学習ステップについても触れました。

Qtは非常に強力で多機能なフレームワークですが、その核となる概念は比較的シンプルです。特にシグナル&スロット機構と、Qt Designerによる視覚的なUI設計は、Qt開発の大きな魅力です。

この記事が、あなたがQtの世界へ足を踏み入れ、魅力的なGUIアプリケーションを開発するための確かな一歩となることを願っています。学ぶべきことはまだたくさんありますが、今回習得した基本的な知識を土台として、ぜひ様々なウィジェットや機能に挑戦し、あなたのアイデアを形にしてみてください。

GUIプログラミングの世界へようこそ!Qtと共に、あなたの創造性を発揮しましょう。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール