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

标签 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 事件,其中可以设置和取消设置 bool 值,因为窗口被抓取和释放(同时调整大小时):

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 的调用?

最佳答案

考虑在按下鼠标按钮时阻止绘图回调。保存回调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 内部执行此操作。

关于c - 如何在调整窗口大小时暂停 GtkDrawingArea 绘制回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30989762/

相关文章:

c - 我知道这个程序的答案,但我不明白为什么?

c - 一元运算符 and++ 或 --

python-3.x - 在 PyGtk3 中调整 Gtk.DrawingArea 的大小

c++ - gtkmm 可以以编程方式更改类的 css 属性吗?

jquery 检测窗口大小调整

jquery - 在 jQuery 中使用 .css 方法设置宽度,以窗口调整大小为条件

c - 如何在多线程程序中防止SIGPIPE?

c - 使用指针数组的选择排序

c - 如何删除 GtkEntryCompletion 的所有操作

javascript - 使用 jquery 根据内容和视口(viewport)高度更改 div 的位置