我有一些用Gtk+编写的C代码,该代码使用Cairo和一个计时器进行了一些动画处理。在大多数情况下,当我单击关闭应用程序图标时,都会在终端上收到以下消息:



现在,我假设这是有问题的,因为在我关闭应用程序的那一刻,计时器被触发并且访问了主窗口小部件,但是此后该小部件已被销毁。确定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 );
}

我假设必须有某种方法来测试window是否仍处于事件状态和有效状态?

最佳答案

您的问题很微妙。这通常是由于GObject/GtkObject的所有权和破坏规则而发生的。让我提醒他们:

  • GObject只是计数引用。当计数达到0时,它们将被销毁。一个新创建的对象的计数为1。
  • GInitiallyUnowned s也被引用计数,并且当计数达到0时也会被销毁。但是新创建的对象具有 float 计数。这意味着第一次增加计数时,实际上并没有增加计数,但浮点计数却沉没了,即转换为正常引用值。
  • GtkObject GInitiallyUnowned对象,因此它们具有不可思议的 float 计数。

    但是您可能知道所有这一切...现在,我的问题是:



    实际上,这很容易,GTK框架列出了所有这些内容,并保留了每个可见GtkWindow的引用。但是,另一个问题是:



    您还记得gtk_widget_destroy()函数和destroy信号吗?它们恰好是这样的:当您想删除顶级GtkWindow时,您调用gtk_widget_destroy(),它将激活信号destroy,该信号由GTK框架接收,该信号删除了实际的窗口并释放了对对象的引用。

    这是您出现问题的原因:如果GTK框架保留了对GtkWindow的唯一现有引用,则实际上释放了该对象。如果这样,您的计时器将尝试访问它,它将失败,因为该窗口不再存在。

    最后,这是(希望)解决方案:
  • 启动计时器时,在窗口上调用g_object_ref()/g_object_ref_sink()。同时向窗口的destroy信号注册一个处理程序。
  • 在窗口的destroy信号的处理程序中:在窗口上调用g_object_unref()并停止计时器。

  • 当然,此部分解决方案也应该起作用,因为不发送destroy信号也不会破坏窗口:
  • 向窗口的destroy信号注册一个处理程序。
  • 在窗口的destroy信号的处理程序中:停​​止计时器。

  • 但是,当您实际上保持指向对象的引用计数器时,认为这是一种好习惯。

    关于c - 如何确定GTK小部件是否已被破坏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11037988/

    10-12 17:44