Yamamoto's Laboratory
 
Version 3
基本
 
Version 4
 
 

Qtの学習方法

Qtの使い方をマスターしたければ、最初、TROLLTECH社のTutorial(#1, #2)を見ることをおすすめします。ただし、英語です。日本語で学びたければ、日本KDEユーザ会(JKUG)Qt チュートリアル-14段階あたりを見るのが良いでしょう。

また、次のような書籍もあります。最後の本は英語はあるが、良さそう。

著者 題名 発行所 ISBN
M. K. Dalheimer Qtプログラミング入門 (株)オライリー・ジャパン ISBN4-87311-007-6
D. Slin 24時間集中講座 Qtプログラミング (株)ピアソン・エデュケーション ISBN4-89471-357-8
J. Blanchette 他 C++ Gui Programming With Qt 3 Prentice Hall Ptr ISBN: 0131240722

実際、プログラムを作成するとなると、マニュアルが必要になります。非常に優れたドキュメントが、「Qt Reference Documentation」として公開されています。また、html形式で同じものディスクに保存されているはずです。ブラウザをつかって、file:///usr/share/doc/qt-devel-3.3.4/html/index.html を見てください。Qtの開発には必要なこと、全てが書かれているはずです。

とりあえずウィンドウをつくる

プログラムの内容

とりあえずウィンドウができるだけで、なにも起こりません。

ソースプログラム

1〜2行目は特に説明する必要も無いでしょう。QApplication, QWidget クラスを使用するためにヘッダーファイルを読み込んでいます。5行目で、QApplicationクラスのオブジェクトを生成しています。このオブジェクトは、Qtを使うときに必ず1つだけ必要です。C/C++のmain関数みたいなものか・・・。7行目でQWidgetクラスのオブジェクトmainwindow を作っています。ここでは、

      QWidget mainwindow;

としないで、わざわざnewを使ってオブジェクトを生成しています。当然、newを使わないこの方法でオブジェクトを生成できますが、問題があるようです。そのことについて、「Qtプログラミング入門」(ISBN4-87311-007-6)のp.19には、以下のように書かれています。

Qtでは、ウィジェットは必ずヒープ上に作成するべきである。ウィジェットは、親ウィジェットが破棄されるときに自動的に破棄されるからである。Qt入門者が犯しがちな誤りとして、スタック上(すなわち、newを使わずに)ウィジェットを作成してしまうことがある。これはきわめて見つけにくいバグとなる。
・・・
ウィジェットは常に(newを使用して)ヒープ上に作成する、ということを覚えておいてほしい。

9行目で、mainwondowをこのQtプログラムのメインウィジェットと決めています。メインウィジェットとは、それが閉じられたときにアプリケーションが終了するものを言います。10行目で、mainwindowの show()を呼び出して、画面に表示しています。そして、最後の11 行目でexec()を呼び出してQtに制御を移します。

ウインドウを表示するプログラム (window_only.cpp)

      01: #include <qapplication.h>
      02: #include <qwidget.h>
      03: 
      04: int main(int argc, char **argv){
      05:   QApplication window(argc, argv);
      06: 
      07:   QWidget *mainwindow = new QWidget;
      08: 
      09:   window.setMainWidget(mainwindow);
      10:   mainwindow->show();
      11:   return window.exec();
      12: }

コンパイルと実行

Makefileを自分で書く

コンパイル方法はいろいろとありますが、私は以下の Makefile を使いました。Qtのバージョンにより、少し書き換える必要があるかもしれません。この方法よりも、qmakeを使うことを勧めます。

以下のようにするとコンパイル・実行できるはずです。もし、コンパイル時にエラーが出るのならば、MakefileのQTDIRのディレクトリーあるいは、LDFLAGSの-lqt-mtあたりを疑ってください。あるいは、qmakeを使ってください。

$ make
$ ./window

ビルド用ファイル (Makefile)

CXX=g++
QTDIR=/usr/lib/qt-3.3
CXXFLAGS = -Wall -I$(QTDIR)/include
LDFLAGS = -lqt-mt  -L$(QTDIR)/lib

window:window_only.cpp
	$(CXX) $(CXXFLAGS) $(LDFLAGS) window_only.cpp -o window

qmakeによりMakefileを生成

Makefileを書くのが面倒くさいと言う人のために、もっと良い方法が用意されています。次のようにすると、自動的にMakefileが作成されます。

$ qmake -project
$ qmake

最初のコマンドで、.pro(project)ファイルが作られます。2番目のコマンドで、そのprojectファイルをもとに、Makefileを作ります。後は、

$ make

のようにmakeするだけで、実行ファイルができます。そして、

$ ./window_only

とすると実行できるでしょう。

実行結果

次のウィンドウが表示されます.

ウィンドウにタイトルを付ける

プログラムの内容

ウィンドウにタイトルをつけて、サイズを指定することにします。

ソースプログラム

8〜11行を追加しました。メンバー関数名から、その内容は推測できるでしょう。8行目でウィンドウのタイトルを指定しています。9〜10行目でウィンドウの最大と最小寸法(ピクセル)を指定しています。11行目で表示するときのサイズを決めています。

8〜11行で使われているメンバーの詳細については、Trolltech社のQWidget Class Reference、あるいはオンラインマニュアルを見てください。

タイトル付きウインドウ (window_title.cpp)

01: #include <qapplication.h>
02: #include <qwidget.h>
03: 
04: int main(int argc, char **argv){
05:   QApplication window(argc, argv);
06: 
07:   QWidget *mainwindow = new QWidget;
08:   mainwindow->setCaption("hajimete no Qt");
09:   mainwindow->setMaximumSize(500,300);
10:   mainwindow->setMinimumSize(250,150);
11:   mainwindow->resize(400,240);
12: 
13:   window.setMainWidget(mainwindow);
14:   mainwindow->show();
15:   return window.exec();
16: }

実行結果

以下の通りコンパイルして、実行ファイルを作成します。

$ qmake -project
$ qmake
$ make

実行すると、以下のようなウィンドウが現れます。ちゃんとタイトルが書かれていますし、サイズも反映されています。サイズを変更してみましょう。

ラベルを追加する

プログラムの内容

先ほど作成したウィンドウにラベルを追加しよう。

ソースプログラム

14〜18行を追加しました。

14行 QLabelクラスで定義されるmy_labelというウィジェットを追加しています。その親ウィジェットは、mainwindowです。
15行 QLabelはQFrameを継承しており、ここでラベルのフレームのスタイルを決めています。
16行 ラベル内で、表示するテキストを決めています。
17行 ラベル内のテキストの位置を決めている。
18行 ラベルの位置を決めています。親ウィジェットの(50,100)ビクセルの位置がラベルウィジェットの左上、そしてそのサイズは幅300ピクセル、高さ50ピクセルと設定しています。

ラベルを表示 (window_label.cpp)

01: #include <qapplication.h>
02: #include <qwidget.h>
03: #include <qlabel.h>
04: 
05: int main(int argc, char **argv){
06:   QApplication window(argc, argv);
07: 
08:   QWidget *mainwindow = new QWidget;
09:   mainwindow->setCaption("hajimete no Qt");
10:   mainwindow->setMaximumSize(500,300);
11:   mainwindow->setMinimumSize(250,150);
12:   mainwindow->resize(400,240);
13: 
14:   QLabel *my_label = new QLabel(mainwindow);
15:   my_label->setFrameStyle( QFrame::Panel | QFrame::Sunken );
16:   my_label->setText("Hello World.\nIt's fun to creat a program.");
17:   my_label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
18:   my_label->setGeometry(50,10,300,50);
19: 
20:   window.setMainWidget(mainwindow);
21:   mainwindow->show();
22:   return window.exec();
23: }

実行結果

ボタンを追加する

プログラムの内容

ボタンを追加しましょう。そのボタンを押したら、プログラムが止まるようにします。ここで、シグナルとスロットを使います。

ソースプログラム

qpushbutton.hとqfont.hをインクルードして、22〜25行を追加しました。

22行QPushButtonクラスのプッシュボタンをmy_buttonを追加しています。ボタンの表示名は、"Quit"で、親ウィジェットはmainwindowです。
23行ボタンの位置(150,100)とサイズ(幅100,高さ50)を決めています。単位はピクセルです。
24行ボタン名を表示する場合のフォント(Times)とサイズ(20ポイント)、スタイル(Bold)を決めています。
25行my_buttonのプッシュボタンが押されたときclicked()、シグナルが発せられ、qAppのスロットquit()が実行される。

ボタンを追加 (window_button.cpp)

01: #include <qapplication.h>
02: #include <qwidget.h>
03: #include <qlabel.h>
04: #include <qpushbutton.h>
05: #include <qfont.h>
06: 
07: int main(int argc, char **argv){
08:   QApplication window(argc, argv);
09: 
10:   QWidget *mainwindow = new QWidget;
11:   mainwindow->setCaption("hajimete no Qt");
12:   mainwindow->setMaximumSize(500,300);
13:   mainwindow->setMinimumSize(250,150);
14:   mainwindow->resize(400,240);
15: 
16:   QLabel *my_label = new QLabel(mainwindow);
17:   my_label->setFrameStyle( QFrame::Panel | QFrame::Sunken );
18:   my_label->setText("Hello World.\nIt's fun to creat a program.");
19:   my_label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
20:   my_label->setGeometry(50,10,300,50);
21: 
22:   QPushButton *my_button = new QPushButton("Quit", mainwindow);
23:   my_button->setGeometry(150,100,100,50);
24:   my_button->setFont(QFont("Times", 20, QFont::Bold));
25:   QObject::connect(my_button, SIGNAL(clicked()), qApp, SLOT(quit()));
26:   
27: 
28:   window.setMainWidget(mainwindow);
29:   mainwindow->show();
30:   return window.exec();
31: }

実行結果

クラスにする

プログラムの内容

単純なものは別にして、GUIはクラスを使うのが普通であろう。そこで、今まで作成したウィンドウをクラスを使って記述してみる。

ソースプログラム

7行my_windowというクラスを定義しています。これは、QWidgetクラスを継承しています。
8行publicなメンバー関数として、コンストラクターを定義しています。
12行プライベートなQLabelクラスのポインターとして、my_labelを定義しています。
13行プライベートなQPushButtonクラスのポインターとして、my_buttonを定義しています。
17-37行コンストラクターmy_window()の実装です。

クラスにする (window_class.cpp)

01: #include <qapplication.h>
02: #include <qwidget.h>
03: #include <qlabel.h>
04: #include <qpushbutton.h>
05: #include <qfont.h>
06: 
07: class my_window : public QWidget{
08:  public:
09:   my_window();
10: 
11:  private:
12:   QLabel *my_label;
13:   QPushButton *my_button;
14: };
15: 
16: my_window::my_window(){
17:   this->setCaption("hajimete no Qt");
18:   this->setMaximumSize(500,300);
19:   this->setMinimumSize(250,150);
20:   this->resize(400,240);
21: 
22:   QPushButton *my_button = new QPushButton("Quit", this);
23:   my_button->setGeometry(150,100,100,50);
24:   my_button->setFont(QFont("Times", 20, QFont::Bold));
25: 
26:   my_label = new QLabel(this);
27:   my_label->setFrameStyle( QFrame::Panel | QFrame::Sunken );
28:   my_label->setText("Hello World.\nIt's fun to creat a program.");
29:   my_label->setAlignment(AlignVCenter | AlignHCenter);
30:   my_label->setGeometry(50,10,300,50);
31: 
32:   connect(my_button, SIGNAL(clicked()), qApp, SLOT(quit()));
33: }
34: 
35: 
36: int main(int argc, char **argv){
37:   QApplication a(argc, argv);
38: 
39:   my_window *w = new my_window();
40:   a.setMainWidget(w);
41:   w->show();
42:   return a.exec();
43: }

実行結果



no counter