本想用GTK繪製一些幾何地圖,然而發現網路上多只有Reference,而實作類似的簡易GTK程式不多,於是寫了一個當作練習。
其中GtkWidget *window表示最外層的視窗,GtkWidget *drawingArea被包在window裡面,為可以畫畫的地方(這裡在上面畫一個Rectangle)。
#include <"gtk/gtk.h"> // Three main elements of this program. GtkWidget *window; GtkWidget *drawingArea; GdkPixmap *pixMap; // Functions static void createWindow(); static void createDrawingArea(); static void layoutSetting(); static void show(); static void draw(); // Event handlers static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event); static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event); static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data); static void destroy(GtkWidget *widget, gpointer data); /* * Main Function */ int main(int argc, char **argv){ gtk_init(&argc, &argv); //initializations createWindow(); createDrawingArea(); //setup layout layoutSetting(); //show show(); draw(); gtk_main(); return 0; } /* * Function : createWindow * Setup window as a new gtk_window, and connect the "delete_event" and * "destroy" signal to handlers. */ static void createWindow(){ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_container_set_border_width(GTK_CONTAINER(window), 40); gtk_window_set_title(GTK_WINDOW(window), "Blocking Practice"); //event handling g_signal_connect(window, "delete-event", G_CALLBACK(delete_event), NULL); g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL); } /* * Function : createDrawingArea * Setup the drawingArea, and connect the "expose_event" and "configure_event" * events to their handlers. */ static void createDrawingArea(){ drawingArea = gtk_drawing_area_new(); //event handling gtk_signal_connect(GTK_OBJECT(drawingArea), "expose_event", (GtkSignalFunc)expose_event, NULL); gtk_signal_connect(GTK_OBJECT(drawingArea), "configure_event", (GtkSignalFunc)configure_event, NULL); gtk_widget_set_events(drawingArea, GDK_EXPOSURE_MASK); //setup size gtk_drawing_area_size(drawingArea, 600, 600); } /* * Function : layoutSetting * Contain "drawingArea" into "window". */ static void layoutSetting(){ gtk_container_add(GTK_CONTAINER(window), drawingArea); } /* * Function : show * Show the elements. */ static void show(){ gtk_widget_show(drawingArea); gtk_widget_show(window); } /* * Function : delete_event * Event handler for the "delete_event" from "window" */ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data){ g_print("Quit!\n:"); gtk_main_quit(); return FALSE; } /* * Function : destroy * Event handler for the "destroy" from "window" */ static void destroy(GtkWidget *widget, gpointer data){ gtk_main_quit(); } /* * Function : draw * Draw a sample rectangle located at (100,150) with 20-width and * 30-height. */ static void draw(){ //setup a gdk rectangle GdkRectangle rect; rect.x = 100; rect.y = 150; rect.width = 20; rect.height = 30; //draw on "drawingArea" gdk_draw_rectangle(pixMap, drawingArea->style->white_gc, TRUE, rect.x, rect.y, rect.width, rect.height); gtk_widget_queue_draw_area(drawingArea, rect.x, rect.y, rect.width, rect.height); } /* * Function : expose_event * Event handler for the "expose_event" from "drawingArea" */ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event){ gdk_draw_drawable(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; } /* * Function : configure_event * Event handler for the "configure_event" from "drawingArea" */ static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event){ if(pixMap) g_object_unref(pixMap); pixMap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); gdk_draw_rectangle(pixMap, widget->style->black_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); return TRUE; }
先吐嘈 coding style:
ReplyDelete1. 函式命名小寫底限分隔還是駱駝背,選一個一致使用, i.e.
不要又 expose_event 又 createWindow
Linux 下 C 程式,小寫底限分隔為主流(受 GNU 與 Linux Kernel 影響)
2. 函式開始的大括號,寫在下一行
不要再『發明』自己的風格。重點是從主流的 Linux kernel 或 GNU coding style 中選一個一致使用,不同程式語言如 C, C++, Java 與 Javascript coding style 不要混。
你的 show() 內可用 gtk_widget_show_all:
http://developer.gnome.org/gtk/2.24/GtkWidget.html#gtk-widget-show-all
程式寫了很長,還沒寫到 OpenGL 啊
GtkDrawingArea 的範例,你執行 gtk-demo 就有一個
謝謝學長的建議,關於命名、括號我會改正,另外OpenGL一事是糟糕的筆誤,已經修改。
ReplyDelete我有一個用 gtk 與 cairo 話螢幕上鍵盤的 Python 程式:
ReplyDeletehttp://itrs.tw/hg/keyshow/file/567100a3b03f/itrs/keyshow.py
給你參考一下。這是幾年前寫的,有些地方不建議你模仿,但畫圖的滿單純的