我正在创建一个GTK + 3应用程序,该应用程序在GtkDrawingArea小部件中使用Cairo绘制动画。我遇到了视觉故障,例如下图所示。这些仅针对单个帧出现,每帧可能不存在,或者一个或多个。我正在寻求帮助来确定可能的问题。这是我的代码的详细信息:
在我的主要方法中,在开始gtk_main()
循环之前,我挂了一个超时。
g_timeout_add(50, queue_draw, gtk_builder_get_object(builder, "window"));
"window"
是我的GtkWindow的ID。 queue_draw
函数如下:
gboolean queue_draw(gpointer user_data)
{
gtk_widget_queue_draw(GTK_WIDGET(user_data));
return TRUE;
}
我认为我可以将GtkDrawingArea对象而不是整个GtkWindow传递给此函数,但是在那种情况下动画会消失。我也对此行为感兴趣,但这不是我的主要问题。
我的GtkDrawingArea的绘制信号被钩接到函数gboolean drawing_area_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
上。在这种方法中,我通过惰性画家的算法绘制3D条形图,每个条形由三个平行四边形组成,并且这些条形按z顺序绘制。
这不是我的计算机无法跟上帧渲染,以某种方式损坏帧缓冲区的问题。我将超时设置为1000ms,以捕获下面的图像。
我尚未致电gtk_widget_set_double_buffered()
。
我无法使用XMing作为X服务器在Linux的Windows子系统(WSL)上观察到该问题,这使我认为这可能是库问题或某些行为不明确的问题。
第一张图片是我的程序在正常运行期间的视觉故障。在第二篇中,我修改了代码,并将条形的高度固定为平缓的渐变。这样可以更好地了解问题,但仍然令人困惑。
开发库软件包详细信息:
$ dpkg --list | egrep 'lib(cairo|gtk).*-dev'
ii libcairo2-dev:amd64 1.15.10-2ubuntu0.1 amd64 Development files for the Cairo 2D graphics library
ii libgtk-3-dev:amd64 3.22.30-1ubuntu3 amd64 development files for the GTK+ library
图书馆元信息的详细信息:
$ pkg-config --modversion gtk+-3.0 glib-2.0 gdk-pixbuf-2.0 cairo
3.22.30
2.58.1
2.36.11
1.15.10
x11详细信息:
$ xdpyinfo | head -n 5
name of display: :0
version number: 11.0
vendor string: The X.Org Foundation
vendor release number: 12001000
X.Org version: 1.20.1
Linux详细信息(实际上是Zorin OS 15而非Ubuntu 18.04):
$ uname -a
Linux <hostname> 4.18.0-25-generic #26~18.04.1-Ubuntu SMP Thu Jun 27 07:28:31 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
编辑:这是该问题的另一个非常有趣的屏幕截图。
答案 0 :(得分:3)
拳头,在主窗口上调用gtk_widget_queue_draw
没有意义,因为仅需要GtkDrawingArea
进行高频更新。重新绘制您未与之交互的控件会增加开销,而没有任何价值。
接下来,我在您的UI中看不到任何想要不断重绘绘图区域的内容。您应该对事件做出反应来重新绘制:左侧面板中已更改的参数值,或者用户单击绘图区域以更改视点(如果您支持的话)。您可能会触发超时,以响应控制更改,并在更改另一个更改时重新初始化该超时,以便让用户在半秒钟内更改所需的所有设置,然后显示最终结果而不是中间更改。当控件的值可以像您使用的GtkSpinButton
一样快速变化时,这很有用。
从您的测试中,如果每秒而不是每50ms调用一次绘图代码会为您提供结果,那么问题很可能出在您的绘图代码中,而不是GTK +绘制它的方式上。为确保这种情况,您可以禁用重绘的超时源,并添加一个按钮,当单击该按钮时将触发单个重绘。这样,整个频率问题就变得不那么重要了,您仍然应该拥有那些渲染错误。
下一步是向我们展示draw
信号处理程序中的代码,因为该错误可能位于此处。如果要调试它,则可以拆分图形,以便在绘制每个直方图条之后将要绘制的开罗曲面保存到文件中。然后使用图像编辑器逐个查看更改,您将看到问题发生在哪个图像上。通过一些日志记录,您将看到哪些值触发了问题。