Qt/C++ による GUI ソフト 1:メインウィンドウ
Qt では,メインウィンドウを作成するためのクラスは QMainWindow と言います.
メインウィンドウを有するプログラムを作成するには.QMainWindow クラスを継承したクラスを作成し.それに色々な機能を追加していくのが一般的です.
GUI アプリケーションの構成部品.あるいはコンポーネントのことをウィジェットといいます.
Qt には QWidget という基本的なウィジェットのクラスがあります.
ボタンやラベルなど.多くのウィジェットは QWidget クラスを継承したクラスです.QMainWindow クラスも QWidget を継承したクラスです.
インフォメーション
インストールした Debian パッケージ
このページは Debian 13 trixie で作成しています.
| パッケージ名(バージョン) | 注 |
| g++(14.2.0) | GNU C++ コンパイラ |
| make(4.4.1) | コンパイルを制御するユーティリティ |
| qt6-base-dev(6.8.2) | Qt6 アプリケーションのビルドに使用されるヘッダ開発ファイル |
ドキュメント
インストールした Debian パッケージとはバージョンが異なります.細かいところでは差異が現れてくるかもしれません.
- このページでは Widgets Tutorial を主な参考資料して勉強します.このページ作成時点でのバージョンは 6.10.1 でした.
- いくつかの説明は.クラスリフアレンス All C++ Classes を参考にしています.バージョンは 6.10 でした
- ここでは.Makefile 作成ツールとして qmake を使います.qmake に関するドキュメントには.qmake Manual があります
qmake については.実行ファイルの作成から共有ライブラリ.動的ライブラリの作成と利用までの練習結果を.qmake を使ったビルドに記しています.
目次(ページ内リンク)
- QWidget のインスタンス化:チュートリアルを参考にして QWidget を表示するプログラムを作成します
- QMainWindow のインスタンス化:QWidget を表示するプログラムを改変して QMainWindow を表示するプログラムを作成します
- メインウィンドウを表現するクラス:QMainWindow を継承したクラス Main_Window を作成して.それを表示するプログラムを作成します
QWidget のインスタンス化
Qt による GUI プログラムの骨格
Widgets Tutorial は.QWidget を作る際の C++ メイン関数の書き方から始まっています.
Qt で GUI プログラムを作成するときの基本的なスタイルだと思います.
一部改変して引用します.
#include <QApplication>
#include <QtWidgets>
//必要に応じてヘッダファイルをインクルードする
int main(int argc, char *argv[]) {
QApplication app(argc, argv); //ウィジェット固有の初期化と終了を処理するためのインスタンス
//ウィジェットのセットアップと表示をおこなう
return app.exec(); //メインイベントループに入り、exit() が呼び出されるまで待機
}
コード内で QApplication インスタンスを作成しています.クラスリファレンスの QApplication から抜粋すると,
QApplication は,
- ウィジェット固有の初期化処理や終了処理をおこなうオブジェクトです
- そのため,ユーザーインターフェースに関連する他のオブジェクトを作成する前に作成する必要があります
- exit() が呼び出されるまで待機した後、exit() に設定された値を返します
- quit() 経由で exit() が呼び出された場合は 0 を返します
- 一般的なコマンドライン引数も処理します.ここでは,int argc, char *argv[] を処理しています
ソースコード
チュートリアルの次のページは Widgets Tutorial - Creating a Window というタイトルです.タイトルには "Window" とありますが.作成しているのは QWidget です.
チュートリアルではウィジェットのサイスを設定したり.タイトルを付けたりしていますが.コードを簡略化するためにここでは省略し,次のセクションに回します.
一方で.QWidget のコンストラクタ引数を与えてみました.ただし.デフォルト引数と同じなので動作は代わりません.
クラスリファレンスを見ると.QWidget のコンストラクタは.
QWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
と宣言されています.
第一引数は.親ウィジェットのなかに子ウィジェットを作成するような場合に利用します.親ウィジェットが nullptr の場合は.そのウィジェットはデスクトップ上に表示されます.
子ウィジェットは親ウィジェットが削除されると自動的に削除されます.
第二引数は.ウィンドウのフレームをカスタマイズするために設定します.
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
//ウィジェットのインスタンス化
QWidget widget(nullptr, Qt::WindowFlags()); //コンストラクタ引数を与えてみた.与えているのはデフォルト引数
widget.show(); //せっかく QWidget を作成したのだが.ここでは show() を呼び出しているだけ
return app.exec(); //exit() が呼び出されるまで待機した後、exit() に設定された値を返す
}
ビルドと実行
プロジェクトファイル
ここでは.Makefile 作成ツールとして qmake を使います.qmake の使い方は qmake を使ったビルドにまとめています.
上のソースコードを main.cc という名前で tmp というディレクトリに保存したとします.とりえあず以下の手順でビルドできます.
~/tmp$ qmake6 -project
とすれば,tmp.pro というプロジェクトファイルが生成します.プロジェクトファイルは,qmake が Makefile を作成するときに参照するファイルで qmake Language で記述されています.
ここで,プロジェクトファイルを少し編集します.
QWidget またはその継承クラスのヘッダをインクルードした場合は,
tmp.pro に QT += widgets
行を追加します.クラスリファレンスのページに書いてあります.この場合は,QWidget Class.
tmp.pro からコメント行を削除して,QT += widgets 行を追加したものを示します.
"TEMPLATE = app" というのはアプリケーションをビルドするという指示です.ライブラリなら "lib".
"TARGET = tmp" というのは,生成する実行ファイル名を設定している行です.デフォルトでは作業ディレクトリ名が設定されます.
TEMPLATE = app
TARGET = tmp
INCLUDEPATH += .
SOURCES += main.cc
QT += widgets
ビルドと実行
~/tmp$ qmake6
とすれば Makefile が生成します.したがって,
~/tmp$ make
とすれば,ビルドが行われます.
~/tmp$ ./tmp &
とすると画像のようなウィンドウが表示されます
QMainWindow のインスタンス化
基本的に,上のコードで使った QWidget をその継承クラスである QMainWindow に変更するだけです.
QMainWindow クラスは名前から想像できるように.アプリケーションのユーザーインターフェース構築用に設計されたクラスです.メニューバーなどを簡単に取り付けることができます
クラスを変更するだけでは面白みがないので,ウィンドウサイズとタイトルバーの設定をして見た目を少し変更します.
ソースコード
main.cc
#include <QApplication>
#include <QMainWindow>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
//メインウィンドウを作成して表示
QMainWindow window(nullptr, Qt::Window);
window.resize(320, 240); //ウィンドウサイズの設定.親クラス QWidget の関数
window.setWindowTitle("QMainWindow"); //タイトルバーに表示される文字列.同上
window.show(); //同上
return app.exec();
}
window.pro
プロジェクトファイルは.qmake -project を使わなくても,上のセクションのものを流用できます.
せっかくなので.生成する実行ファイルの名前を変更しました.
TEMPLATE = app
TARGET = q_main_window
INCLUDEPATH += .
SOURCES += main.cc
QT += widgets
ビルドと実行
上と同じ手順です.ただし,生成する実行ファイルの名前を変更しています.
~/tmp$ qmake6
~/tmp$ make
~/tmp$ ./q_main_window &
として実行すると.上のセクションよりし小ぶりでタイトルバーに "QMainWindow" と記されたたウィンドウが表示されます.
メインウィンドウを表現するクラス
上のセクションでは QMainWindow クラスのインスタンスを作成して表示しました.
ソフトウェア開発では.メインウィンドウにメニューバーを追加したりボタンを追加するなどして.メインウィンドウに独自の機能を与えます.
それを実現するためのクラスとして.このセクションでは QMainWindow クラスを継承する Main_Window クラスを作成します.
Main_Window クラスは自分で宣言・定義するクラスなので,メニューを追加したりレイアウトを設定したり,自由にできます
ソースコード
main_window.h
QMainWindow クラスを継承する独自クラス Main_Window を宣言します.
この Main_Window クラスは.単に QMainWindow クラスを継承したというだけです.現段階で機能的な違いはありません.
#include <QMainWindow>
class Main_Window : public QMainWindow {
public:
//ここではコンストラクタ引数は QMainWindow クラスと同じとした
Main_Window(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
//独自の変数や関数を宣言して機能を盛る
};
main_window.cc
独自クラス Main_Window の定義ファイルです.
コンストラクタでウィンドウのサイズとタイトルバーに表示される文字列を設定しています.
#include "main_window.h"
Main_Window::Main_Window(QWidget *parent, Qt::WindowFlags f)
: QMainWindow(parent, f) //コンストラクタ引数を QMainWindow のコンストラクタに渡す
{
//main 関数 から呼び出していたのを Main_Window のコンストラクタから呼び出すように変更
resize(320, 240);
setWindowTitle("Main_Window");
}
//独自の変数や関数を定義する
main.cc
独自クラス Main_Window を作成して表示するようにコーディングしています.
#include "main_window.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Main_Window window(nullptr, Qt::Window); //デフォルト引数を設定しているので Main_Window window; でも同じ
window.show();
return app.exec();
}
tmp.pro
プロジェクトファイルでは.ソースファイルの数と種類が増えました.
TEMPLATE = app
TARGET = my_window
INCLUDEPATH += .
QT += widgets
SOURCES += main.cc main_window.cc
HEADERS += main_window.h
ビルドと実行
上と同じ手順です.
~/tmp$ qmake6
~/tmp$ make
~/tmp$ ./my_window &
として実行すると.上のセクションと同じウィンドウが表示されます.
次のページ 2:メニューバーでは,Main_Window クラスにメニューバーを追加します.