现状: 我有一个带有事件窗口的自定义小部件(MyWidget) 问题:如果我创建,显示然后,稍后隐藏和销毁小部件,我会从应用程序中收到以下消息:
Gdk-WARNING **: losing last reference to undestroyed window
我发现了什么:我查看了gdkwindow.c
文件,并在GDK_WINDOW_DESTROYED(window) == FALSE
时报告此消息。所以我不明白的是我应该如何正确地破坏我的窗口,以便最终调用gdk_window_destroy()
函数。我认为最好的地方是Gdk::~Window()
析构函数。但它是空的。而且gdk_window_destroy()
文件中根本没有gdkwindow.cc
。
on_realize()
和on_unrealize()
回拨在下面。
class MyWidget : public Gtk::Widget
{
...
private:
Glib::RefPtr<Gdk::Window> _event_window;
...
};
void Gtk::MyWidget::on_realize()
{
GdkWindowAttr attributes;
const Allocation & allocation = get_allocation();
attributes.event_mask = GDK_BUTTON_PRESS_MASK;
attributes.x = allocation.get_x();
attributes.y = allocation.get_y();
attributes.width = allocation.get_width();
attributes.height = allocation.get_height();
attributes.wclass = GDK_INPUT_ONLY;
attributes.window_type = GDK_WINDOW_CHILD;
_event_window = Gdk::Window::create(get_parent_window(), &attributes, GDK_WA_X | GDK_WA_Y);
_event_window->set_user_data(Widget::gobj());
set_window(get_parent_window());
set_realized();
}
void Gtk::MyWidget::on_unrealize()
{
_event_window->set_user_data(NULL);
_event_window.reset();
set_realized(false);
}
答案 0 :(得分:0)
事实证明,用Gdk::Window::create()
破坏你创建的GDK窗口的最正确的方法是..猜猜是什么?在自定义窗口小部件的Gtk::Widget::unrealize()
方法中调用on_unrealize()
,因为除了其他内容,此基本方法为窗口小部件的GDK窗口调用gdk_window_destroy()
。为此,您的小部件 为“窗口”(即您应该在构造函数中调用set_has_window(true);
并在set_window(<your allocated GDK window>);
回调中调用on_realize()
。非常明显的方法,isn不是吗?
我还应该谈谈Gtk::Widget::realize()
。与Gtk::Widget::unrealize()
不同的是,如果您的小部件没有 GDK窗口,则应该仅调用Gtk::Widget::realize()
(该方法假设为断言)。< / p>
不幸的是,我没有时间,并希望深入了解它并努力理解为什么这样做以及这种方法有什么原因和后果。否则我会提供更详细的解释。
您可以在GTK的自定义小部件教程中找到官方示例 here。
此外,我的小部件的代码现在看起来像:
class MyWidget : public Gtk::Widget
{
...
private:
Glib::RefPtr<Gdk::Window> _event_window;
...
};
void Gtk::MyWidget::on_realize()
{
GdkWindowAttr attributes;
const Allocation & allocation = get_allocation();
attributes.event_mask = GDK_BUTTON_PRESS_MASK | GDK_EXPOSURE;
attributes.x = allocation.get_x();
attributes.y = allocation.get_y();
attributes.width = allocation.get_width();
attributes.height = allocation.get_height();
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.window_type = GDK_WINDOW_CHILD;
_event_window = Gdk::Window::create(get_parent_window(), &attributes, GDK_WA_X | GDK_WA_Y);
_event_window->set_user_data(Widget::gobj());
set_window(_event_window);
set_realized();
}
void Gtk::MyWidget::on_unrealize()
{
_event_window->set_user_data(NULL);
_event_window.reset();
Widget::unrealize();
// it will call gdk_destroy_window() and
// set_realized(false);
}