我在GNOME Builder上创建了一个示例GTKMM项目。最棒的是,为我的示例项目自动生成了一个示例helloworld代码。由于C++源文件被组织为三个部分:
- 头文件
- 实施文件
- 主文件
我在一个cpp文件中修改了我的示例代码以进行演示:
#include <iostream>
#include <gtkmm.h>
using std::cout;
using Gtk::Application;
using Gtk::Window;
using Gtk::Box;
using Gtk::Button;
using Gtk::Label;
class HelloWindow : public Window
{
Box box;
Button button;
Label label;
public:
HelloWindow();
~HelloWindow();
};
HelloWindow::HelloWindow()
: Glib::ObjectBase("HelloWindow")
, Window()
, box(Gtk::ORIENTATION_VERTICAL)
, button("Clickable button")
, label("Hello World!")
{
set_default_size(320, 240);
bool expand(true), fill(true);
box.pack_start(label, expand, fill);
box.pack_end(button, expand, fill);
add(box);
show_all();
}
HelloWindow::~HelloWindow()
{
cout << "Object successfully destructed!n";
}
static void
on_activate(Glib::RefPtr<Application> app)
{
Window *window = app->get_active_window();
if (not window) {
window = new HelloWindow();
window->set_application(app);
app->add_window(*window);
}
window->present();
}
int main()
{
auto app = Application::create("io.test.window-state-event");
app->signal_activate().connect(sigc::bind(&on_activate, app));
return app->run();
}
关于上述代码的一个有趣的部分是app
连接到on_activate
信号,这意味着用户只能运行该程序的一个实例。如果他试图运行另一个实例,则会显示上一个仍在运行的窗口。
然而,在on_activate()
上使用了new
关键字,这让我有点困惑。当用户关闭HelloWorld窗口时,对象真的被删除了吗?我从C++new
关键字中学到的是,必须记住delete
分配有前一个关键字的任何对象。
此外,析构函数消息";对象已成功销毁"窗口关闭时未打印。
有可能存在故意泄漏,但它是"受控";。作者知道这个方法只会被调用一次。作者还知道内存需要在应用程序的整个生命周期中都处于活动状态。当应用程序关闭时,内存将以某种方式释放(尽管永远不会调用析构函数,但在这种情况下,不需要执行任何命令(
这在这个场景中是非常好的。
如果你想确保Window
对象被删除,你可以保留Window
的unique_ptr
,它会自行处理(感谢@underscore_d注释(:
#include <memory>
static std::unique_ptr<Window> window;
static void
on_activate(Glib::RefPtr<Application> app)
{
if (!window) {
window = std::make_unique<HelloWindow>();
window->set_application(app);
app->add_window(*window);
}
window->present();
}
int main()
{
auto app = Application::create("io.test.window-state-event");
app->signal_activate().connect(sigc::bind(&on_activate, app));
return app->run();
}
最后,我相信作者想保留这个";你好,世界;示例简单简洁,不想添加一些不需要的代码来保持简单简洁。
看看GTKMM文档中关于托管小部件的部分。您应该使用Gtk::make_managed
:的一些变体
if (!window) {
window = Gtk::make_managed<HelloWindow>();
window->set_application(app);
app->add_window(*window);
}
这样,窗口的生存期将由应用程序管理。