如何在调整窗口大小时暂停GtkDrawingArea绘制回调?

时间:2015-06-22 21:03:14

标签: c gtk3 window-resize

我正在开发一个小型GTK +程序,我在其中放置了GtkDrawingArea。我使用它来绘制一个相当具体的数据表示图,结果非常令人满意。

问题是:"图表"有很多数据需要处理,并且经常调用绘制信号的回调。最重要的是,每次窗口(GtkWindow / GtkContainer)调整几个像素大小时都会调用它。为了避免过多地减慢应用程序的速度,我希望"暂停"调整窗口大小时的绘制回调。我们可以想象在此期间整个区域将覆盖一个灰色矩形,或类似的东西......

gboolean draw_callback(GtkWidget* widget, cairo_t* cr, gpointer data){
    /* A lot of drawing with Cairo 
     * This is called WAY too often. */
}

int main(int argc, char* argv[]){
    GtkBuilder* builder;
    GtkWidget *window;
    GtkWidget *draw_area;

    gtk_init(&argc, &argv);
    builder = gtk_builder_new_from_file("myapp.ui");

    window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window"));
    draw_area = GTK_WIDGET(gtk_builder_get_object(builder, "draw_area"));

    g_signal_connect(draw_area, "draw", G_CALLBACK(draw_callback), NULL);

    gtk_widget_show_all(GTK_WIDGET(window));

    g_object_unref(builder);
    gtk_main();

    return 0;
}

注意:调整窗口大小后仍必须执行回调(当发生这种情况时,需要重新计算某些坐标)。我只是试图避免它正在调整窗口大小。

我的第一个想法是将回调连接到check-resize事件,其中可以设置和取消设置布尔值,因为窗口被抓取并释放(在调整大小时):

gboolean resizing = false;

void resize_callback(GtkContainer* container, gpointer data){
    /* Set "resizing"... 
     * Is the window being grabbed? Released? */
}

gboolean draw_callback(GtkWidget* widget, cairo_t* cr, gpointer data){
    if(resizing){
        /* Draw a gray overlay or something if necessary... */
        return true;
    }

    /* Draw the actual stuff here... */
}

int main(int argc, char* argv[]){
    GtkWidget *window;
    GtkWidget *draw_area;

    // ...

    g_signal_connect(window, "check-resize", G_CALLBACK(resize_callback), NULL);
    g_signal_connect(draw_area, "draw", G_CALLBACK(draw_callback), NULL);

   // ...
}

然而,这个事件并不适合我,因为在抓取/释放窗口时(仅当其大小实际发生变化时)不会触发此事件。

有没有办法在抓取和释放窗口时通知(用于调整大小)?或者,在调整窗口大小时,是否有更好的方法可以暂停/简化对draw_callback的调用?

1 个答案:

答案 0 :(得分:1)

在鼠标按钮关闭时,请考虑阻止绘制回调。保存回调ID:

draw_callback_id = g_signal_connect(draw_area, "draw",
                                    G_CALLBACK(draw_callback), NULL);

当检测到按下按钮的信号时,执行

g_signal_handler_block(draw_area, draw_callback_id);

当然,在按钮释放事件之后:

g_signal_handler_block(draw_area, draw_callback_id);

然后,您可以手动触发重绘事件。要进行优化,您可以使用gtk_widget_queue_draw_region()调用,该调用仅重绘指定的矩形。

另一种可能性(尽管我还没试过)可能只是在调整大小或移动时绘制窗口边框。窗口管理器(XFCE)有这个选项,但我还没有看到如何从GTK内部做到这一点。