gtkmm 写 Hello World

目前我们已经可以自己所学的知识来写一个真正的程序了。根据计算机科学的传统,我们现在以 gtkmm 的方式来介绍 Hello World 程序:

源代码

File: helloworld.h (For use with gtkmm 3, not gtkmm 2)

#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:
  void on_button_clicked();

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

#endif // GTKMM_EXAMPLE_HELLOWORLD_H

File: main.cc (For use with gtkmm 3, not gtkmm 2)

#include "helloworld.h"
#include <gtkmm/main.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 (For use with gtkmm 3, not gtkmm 2)

#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;
}

在继续讲解之前,可以尝试着编译并运行这个程序,你会看到这样的结果:

图 3-1Hello 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”的标签。

接下来调用 Windows 类的 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 程序都有这样的一个东西。我们将命令行参数传递给它的构造函数。它会提取自己需要的参数,将剩下的部分留给我们,就像前面描述过的那样。

接着我们创建了 HelloWorld 类的对象,它的构造函数没有参数,当然,它现在还不是可视的。当我们调用 Gtk::Main::run() 并给它提供一个 helloworld 窗口作为参数时,它将显示这个窗口并进入 gtkmm消息循环。在消息循环中,gtkmm 是空闲的,它等待用户的操作并作出相应的反应。当用户关闭窗口时,run() 函数将返回,导致 main() 函数的最后一行将被执行。然后程序就结束了。