如何确定GTK小部件是否已被销毁

Chi*_*era 5 c gtk widget

我有一些Gtk+编写的代码C,它使用一些动画Cairo和一个计时器.大多数情况下,当我点击关闭应用程序图标时,我在终端上收到以下消息:

Gtk-CRITICAL**:gtk_widget_queue_draw:断言`GTK_IS_WIDGET(widget)'失败

现在我假设这是在讨价还价,因为在我关闭应用程序的那一刻,计时器被触发并且主窗口小部件被访问但是后来被破坏了.确定Gtk小部件是否仍然有效且可以引用的常用方法是什么?

违规代码在这里:

gboolean rotate_cb( void *degrees )
{
    rotation += DegreesToRadians((*(int*)(degrees)));
    // Tell our window that it should repaint itself (ie. emit an expose event)
    /* need to only call gtk_widget_queue_draw() if window is still valid / exists */
    gtk_widget_queue_draw(window);
    return( TRUE );
}
Run Code Online (Sandbox Code Playgroud)

我假设必须有一些方法来测试是否window仍然有效且有效?

rod*_*igo 11

你的问题非常微妙.这通常是因为GObject/GtkObject的所有权和破坏规则而发生的.让我提醒他们:

  • GObjects只是计数参考.当计数达到0时,它们被销毁.新创建的对象计数为1.
  • GInitiallyUnowneds也被计数引用,并且当计数达到0时它们也被销毁.但是新创建的对象具有浮动计数.这意味着第一次递增计数时它实际上没有递增,但是浮动计数是沉没的,即转换为正常参考.

GtkObjects GInitiallyUnowned对象,因此它们具有神奇的浮动计数.

但你可能知道这一切......现在,我的问题:

谁拥有可见的主要GtkWindow的柜台?

这实际上很简单,GTK框架有一个列表,并保留每个可见的参考GtkWindow.但是,另一个问题是:

什么时候GTK框架免费提供其GtkWindow的引用?

你还记得gtk_widget_destroy()功能和destroy信号吗?它们正是为了这个:当你想要删除GtkWindow你调用的顶层时gtk_widget_destroy(),它会激活destroyGTK框架接收到的信号,该信号将删除实际窗口并释放对该对象的引用.

这就是你的问题的原因:如果GTK框架保留了唯一的现有引用GtkWindow,则实际释放该对象.如果那时,你的计时器试图访问它,它将失败,因为窗口不再.

在这里,最后,(希望)来了解决方案:

  • g_object_ref()/g_object_ref_sink()启动计时器时调用窗口.还要将处理程序注册到destroy窗口的信号.
  • destroy窗口信号的处理程序中:调用g_object_unref()窗口并停止计时器.

当然,这种局部解决方案也应该有效,因为在不发送destroy信号的情况下窗口不会被破坏:

  • 将处理程序注册到destroy窗口的信号.
  • destroy窗口信号的处理程序中:停止计时器.

但是,当您实际保留指向它们的指针时,增加对象的ref计数器被认为是一种很好的做法.