我有一些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计数器被认为是一种很好的做法.