用 gtkmm 写 Hello World
目前我们已经可以自己所学的知识来写一个真正的程序了。根据计算机科学的传统,我们现在以 gtkmm 的方式来介绍 Hello World 程序:
File: helloworld.h (For use with gtkmm 4)
#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(); ~HelloWorld() override; 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 4)
#include "helloworld.h" #include <gtkmm/application.h> int main(int argc, char* argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<HelloWorld>(argc, argv); }
File: helloworld.cc (For use with gtkmm 4)
#include "helloworld.h" #include <iostream> HelloWorld::HelloWorld() : m_button("Hello World") // creates a new button with label "Hello World". { // Sets the margin around the button. m_button.set_margin(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). set_child(m_button); } HelloWorld::~HelloWorld() { } void HelloWorld::on_button_clicked() { std::cout << "Hello World" << std::endl; }
在继续讲解之前,可以尝试着编译并运行这个程序,你会看到这样的结果:
真让人激动,不是吗?让我们回过头来看一下代码。首先看一下 HelloWorld 类:
class HelloWorld : public Gtk::Window { public: HelloWorld(); ~HelloWorld() override; protected: //Signal handlers: void on_button_clicked(); //Member widgets: Gtk::Button m_button; };
这个类实现了“Hello World”窗口。它由 Gtk::Window 派生,并且只有一个 Gtk::Button 成员。我们已经使用构造函数为该窗口完成了所有的初始化工作,包括挂接消息。在这,已经去掉注释的代码:
HelloWorld::HelloWorld() : m_button("Hello World") { m_button.set_margin(10); m_button.signal_clicked().connect(sigc::mem_fun(*this, &HelloWorld::on_button_clicked)); set_child(m_button); }
注意,我们使用初始化列表的方式给 m_button 对象添加了一个“Hello World”的标签。
接下来调用 Button 类的 set_margin() 方法。这将设置按钮周围空间的大小。
然后,把 m_button 的 clicked 信号挂接到信号处理函数上。这会向 stdout (标准输出) 打印出友好的问候语。
接下来调用 Windows 类的 set_child() 方法将m_button放入窗口。set_child()方法会将部件放入窗口中。
现在让我们来看看程序中没有注释过的 main() 函数:
int main(int argc, char* argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); HelloWorld helloworld; return app->run(helloworld, argc, argv); }
我们首先实例化一个储存在名为 app 的RefPtr智能指针对象,它的类型为 Gtk::Application 。每一个 gtkmm 程序都有这样的一个东西。
接着我们创建了 HelloWorld 类的对象,它的构造函数没有参数,当然,它现在还不是可视的。当我们调用Gtk::Application::run()并给它提供一个 helloworld 窗口和命令行参数时,它将显示这个窗口并进入 gtkmm消息循环。在消息循环中,gtkmm 是空闲的,它等待用户的操作并作出相应的反应。当用户关闭窗口时,run() 函数将返回,导致main()函数的最后一行将被执行。然后程序就结束了。
就像我们之前显示的简单示例一样,这个 Hello World 程序不实用命令行参数。不需要将其传递给run()。