问题描述
我在GNOME Builder上创建了一个示例GTKMM项目。很棒的事情是为我的示例项目自动生成了示例hello world代码。由于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,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
信号,这意味着用户只能运行该程序的一个实例。而且,如果他尝试运行另一个实例,则会显示以前仍在运行的窗口。
但是,在new
上使用了on_activate()
关键字,这让我有些困惑。当用户关闭HelloWorld窗口时,该对象是否真的删除了?我对C ++ new
关键字的了解是,必须记住delete
用前一个关键字分配的任何对象。
此外,析构函数消息“对象已成功破坏!”关闭窗口时不会打印。
解决方法
有可能是故意泄漏,但它是“受控的”。作者知道该方法将仅被调用一次。作者还知道内存需要在应用程序的整个生命周期内保持活动状态。当应用程序关闭时,该内存将以一种或另一种方式释放(尽管不会调用析构函数,但是在这种情况下,不需要执行任何操作)
在这种方案中完全可以。
如果要确保删除Window
对象,可以保留unique_ptr
中的Window
,它会自行处置(由于@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();
}
最终,我确定作者希望保持这个“ Hello,World”示例简单明了,并且不想添加一些实际上不是 的代码>保持简洁简洁。
,请参阅GTKMM文档中有关managed widgets的部分。您应该使用Gtk::make_managed
的一些变体:
if (!window) {
window = Gtk::make_managed<HelloWindow>();
window->set_application(app);
app->add_window(*window);
}
这样,窗口的生存期将由应用程序管理。