我正在开发一个小型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,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,NULL); // ... }
但是这个事件并不适合我,因为在抓取/释放窗口时不会触发它(仅当它的大小实际发生变化时).
有没有办法在抓取和释放窗口时通知(用于调整大小)?或者,在调整窗口大小时,是否有更好的方法来暂停/简化对draw_callback的调用?
解决方法
在鼠标按钮关闭时,请考虑阻止绘制回调.保存回调ID:
draw_callback_id = g_signal_connect(draw_area,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内部做到这一点.