gtkmmでHello World

ここまでに実際に動く例を沢山見て学んできました。ここでは古代より続くコンピュータ科学の伝統にのっとり、Hello Worldのgtkmm風を紹介します:

Source Code

File: helloworld.h

#ifndef GTKMM_EXAMPLE_HELLOWORLD_H
#define GTKMM_EXAMPLE_HELLOWORLD_H

#include <gtkmm/button.h>
#include <gtkmm/window.h>

class HelloWorld : public Gtk::Window
{

public:
  HelloWorld();
  virtual ~HelloWorld();

protected:
  //Signal handlers:
  virtual void on_button_clicked();

  //Member widgets:
  Gtk::Button m_button;
};

#endif // GTKMM_EXAMPLE_HELLOWORLD_H

File: main.cc

#include <gtkmm/main.h>
#include "helloworld.h"

int main (int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  HelloWorld helloworld;
  //Shows the window and returns when it is closed.
  Gtk::Main::run(helloworld);

  return 0;
}

File: helloworld.cc

#include "helloworld.h"
#include <iostream>

HelloWorld::HelloWorld()
: m_button("Hello World")   // creates a new button with label "Hello World".
{
  // Sets the border width of the window.
  set_border_width(10);

  // When the button receives the "clicked" signal, it will call the
  // on_button_clicked() method defined below.
  m_button.signal_clicked().connect(sigc::mem_fun(*this,
              &HelloWorld::on_button_clicked));

  // This packs the button into the Window (a container).
  add(m_button);

  // The final step is to display this newly created widget...
  m_button.show();
}

HelloWorld::~HelloWorld()
{
}

void HelloWorld::on_button_clicked()
{
  std::cout << "Hello World" << std::endl;
}

先に進む前に、コンパイルして実行してみましょう。次のようになるはずです:

Figure 3.1. Hello World

Hello World

ゾクゾクしてきませんか?さあ、コードを調べてみましょう。まずはHelloWorldクラスです:

class HelloWorld : public Gtk::Window
{

public:
  HelloWorld();
  virtual ~HelloWorld();

protected:
  //Signal handlers:
  virtual void on_button_clicked();

  //Member widgets:
  Gtk::Button m_button;
};

このクラスでは "Hello World" ウィンドウを実装しています。これはGtk::Windowから派生し、メンバとしてGtk::Buttonを一つ持っています。ここではコンストラクタを使って、ウィンドウを動作させるための初期化を全て(シグナルを設定することも含めて)行っています。次は、コメントを省略した部分です:

HelloWorld::HelloWorld()
:
  m_button ("Hello World")
{
  set_border_width(10);
  m_button.signal_clicked().connect(sigc::mem_fun(*this,
    &HelloWorld::on_button_clicked));
  add(m_button);.
  m_button.show();
}

初期化子の記述を使ってm_buttonに Hello World とラベルをつけていることに注目してください。

次はWindowのset_border_width()メソッドを呼んでいます。これはウィンドウと、その中にあるウィジットの間のスペースの量を決めています。

それから、シグナルハンドラをm_buttonclickedシグナルにつなぎます。ここでは分かりやすいようにstdoutに挨拶を出力するようにしています。

次はWindowのadd()メソッドを使ってm_buttonをWindowに加えます(add()はこの章のコンテナウィジットのところで書いたGtk::Containerから継承しています)。add()メソッドはウィンドウ内にウィジットを配置します。しかし、ウィジットは表示されません。gtkmmのウィジットは生成された段階では常に不可視の状態にあります。表示させるにはshow()メソッドを呼ばなければいけません。これがその次の行で行っていることです。

さて、プログラムのmain()関数を見てみましょう。コメントを除いたものがこれです:

int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);

  HelloWorld helloworld;
  Gtk::Main::run(helloworld);

  return 0;
}

まずkitと呼ばれるオブジェクトを説明します。これはGtk::Main型のものです。全てのgtkmmプログラムではこの型のオブジェクトを一つは持っていないといけません。コマンドラインの引数をこのコンストラクタに渡すことで、gtkmmに必要とする引数を渡し、残りをこちらで使うことが出来ます。これは以前にも書きました。

次に私たちのHelloWorldクラスのオブジェクトを生成します。コンストラクタは引数をとりません。この段階ではまだ不可視の状態です。Gtk::Main::run()にhelloworldオブジェクトを渡して呼ぶことでウィンドウは表示され、gtkmmイベントループが始まります。イベントループ中はアイドル状態となり、ユーザーからの入力を待機し、適切に処理します。ユーザーがウィンドウを閉じると、run()内から戻ってmain()関数の最後まで実行します。そしてアプリケーションは終了します。