Gtk的絕大多數構件都是支援重繪功能的。什麼是重繪?重繪就是作業系統運行多視窗程序,或是多個有視窗程序時,一個視窗將另一個視窗遮蓋,之後這個在最上面(TopLevel)的視窗被最小化或是關掉之後,其下面的視窗重新顯示出來。這個就叫做“重繪”。
不知道是由於什麼原因,gtk的構件中,GtkDrawingArea就不支援“重繪”,需要程式員手動設定“重繪”,基本上包括重繪的介面一切細節,都要程式員設定。不過還好,gtk提供圖片緩衝pixmap,我們可以將被遮蓋的圖片儲存進pixmap,到需要“重繪”時,再將其“粘貼”到螢幕上。
要做到這一點。我們需要清楚兩點。
1.何時“重繪”?
2.“重繪”在哪裡?
當需要重繪時,會有事件“expose_event”被觸發。調用相應的時間回呼函數,就可以很好地完成“重繪”任務。
首先要在drawing_area中註冊expose_event和相應的回呼函數。
gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
(GtkSignalFunc) expose_event, NULL);
下面是我的回呼函數。
gint expose_event (GtkWidget *widget, GdkEventExpose *event)
{
/* --- Copy pixmap to the window --- */
gdk_draw_pixmap (widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
pixmap,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
return FALSE;
}
第4,5個參數是重繪的矩形地區的左上方初始座標,第6,7參數是重繪的矩形地區的左上方目標座標。
接下來要解決,視窗大小改變時drawing_area的伸縮問題。如果,沒有設定,一旦視窗被最大化,最小化或是展開,縮小,drawing_area又會漆黑一片。
實際上,當視窗初始化,被展開,最大化,最小化時,都會觸發“configure_event”事件。也就是說,設定好“configure_event”的回呼函數,可以很好地解決視窗大小改變的問題。
首先是註冊:
gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
(GtkSignalFunc) configure_event, NULL);
回呼函數:
static gint configure_event (GtkWidget *widget, GdkEventConfigure *event)
{
/* --- Free background if we created it --- */
boolean second=FALSE;
if (pixmap)
{
gdk_pixmap_unref (pixmap);
second =TRUE;
}
/* --- Create a new pixmap with new size --- */
pixmap = gdk_pixmap_new (widget->window,
widget->allocation.width,
widget->allocation.height,
-1);
top_width = widget->parent->parent->allocation.width;
top_height = widget->parent->parent->allocation.height;
update_transform();
if(second)
{
drawscreen();
my_draw_pixmap();
}
return TRUE;
}
“configure_event”回呼函數要做兩件事,
1.視窗初始化時,同樣初始化pixmap。
2.視窗大小改變時,將改變的映像儲存進pixmap中,並通過gtk_draw_pixmap()顯示出來。
由於,原程式需要截獲滑鼠點擊繪圖區時的,游標在繪圖區的座標,以便調用highlight_blocks(float,float)函數。我還要處理繪圖區的“button_press_event”事件。
過程同前兩個事件一樣。
"button_press_event"的註冊:
gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
(GtkSignalFunc) button_press_event, NULL);
"button_press_event"的回呼函數:
gint button_press_event(GtkWidget *widget,GdkEventButton *event)
{
float x,y;
x = XTOWORLD((float)event->x);
y = YTOWORLD((float)event->y);
highlight_blocks(x,y);
gdk_draw_pixmap (widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
pixmap,
widget->allocation.x, widget->allocation.y,
widget->allocation.x, widget->allocation.y,
widget->allocation.width, widget->allocation.height);
return TRUE;
}
通過event參數,我們可以獲得所需的游標座標的資料。