我有一些用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/