3

我想在 GTK+ 窗口上使用 Cairo 显示模拟战场上的当前情况。我的应用程序必须使用提供的框架,该框架在自己的主循环中运行。所以,我不能gtk_main在主线程中调用,必须在单独的线程中启动 GTK+ 主运行循环:

...
g_thread_init(NULL);
g_thread_create(gui_main_loop, data, FALSE, NULL);
...

...
gpointer gui_main_loop(gpointer data)
{
...
    gdk_threads_init();
    gdk_threads_enter();
...
    // Here I make my cute UI
...
    gtk_main();
    gdk_threads_leave();
...
}
...

我已将处理程序附加到我的绘图区域的“绘图”事件:

...
gboolean rendering(GtkWidget *widget, cairo_t *c, gpointer data)
{
    // Here I render my UI using cairo.
    return TRUE;
}
...
// I call this function before gtk_main
g_signal_connect(G_OBJECT(drawing_area), "draw", G_CALLBACK(rendering), data);
...

因此,我的 GTK+ 窗口位于另一个线程中,并且每次调整窗口大小时都会重新绘制。但我需要每秒更新几次,以便监控战场上的当前情况。在每次迭代中,我从主线程调用 invalidate 函数:

...
gdk_window_invalidate_rect(gtk_widget_get_window(drawing_area), NULL, true);
...

但在几秒钟内,用户界面冻结。它对窗口调整大小作出反应,但忽略 gdk_window_invalidate_rect 调用。我究竟做错了什么?

4

1 回答 1

0

您是否尝试过在您的通话中添加gdk_threads_enter/ ?gdk_threads_leavegdk_window_invalidate_rect

你也最好使用gtk_widget_queue_draw而不是gdk_window_invalidate_rect. 但请记住,您需要确保“渲染”回调足够快。你应该测量它。如果您不需要每次都重新绘制完整图像,则在 cairo 中使用剪裁或使用gtk_widget_queue_draw_area代替将有助于提高性能。gtk_widget_queue_draw

于 2012-11-09T10:31:21.997 回答