gdkmm: как уничтожить окно gdk?

Статус кво:
У меня есть собственный виджет (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

Решение

Оказалось, что самый правильный способ уничтожить созданное вами окно GDK Gdk::Window::create() это … угадай что? звонить Gtk::Widget::unrealize() в on_unrealize() метод вашего пользовательского виджета, потому что помимо прочего этот базовый метод вызывает gdk_window_destroy() для окна GDK виджета. И для этого ваш виджет имеет быть «оконным» (то есть вы должны позвонить set_has_window(true); в конструкторе и set_window(<your allocated GDK window>); в on_realize() Перезвоните. Очень очевидный подход, не правда ли?

Я должен также сказать кое-что о Gtk::Widget::realize(), В отличие от Gtk::Widget::unrealize() ты должен позвонить Gtk::Widget::realize() только если ваш виджет не имеет окно GDK (метод предполагает это как утверждение).

К сожалению, у меня не было времени и желания докопаться до сути и постараться понять, почему это было сделано, и какие причины и последствия имеет этот подход. В противном случае я бы дал более подробное объяснение.

Вы можете найти официальный пример из учебника GTK по пользовательским виджетам
Вот.

Также код моего виджета теперь выглядит так:

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);
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]