在 GTK3 中增加了一個 GtkApplicaton 類,便于我們處理多窗口程序,同時有了 Gtkapplication 我們也更容易創建靈活,易用,界面美觀的應用程序。
在前面的幾個例子中,演示了如何利用 GtkApplication 直接創建單個窗口,并知道了在哪里設計我們的 UI 。以及簡單嘗試了 GtkBuilder 。
接下來,我們走進 GtkApplication 。采用面向對象的設計方式設計我們的應用。
我們想要封裝一個 MyApp 和 MyAppWindow , 它繼承了 GtkApplcation 和 GtkApplicationWindow。
首先需要創建如下幾個文件:
main.c : 主函數在此文件。
myapp.c mypp.h : 封裝的 MyApp
myappwindow.c myappwindow.h : 封裝的 MyAppWindow
采用這樣的設計方式,主函數里面只需要一句話,main.c 內容如下:
#include <gtk/gtk.h>#include "myapp.h"int main(int argc , char *argv[]){ //my_app_new() 是我們封裝好的,創建一個 MyApp 的接口 return g_application_run ( G_APPLICATION ( my_app_new() ) , argc , argv );}
接下來是 myapp.c
#include <gtk/gtk.h>#include "myapp.h"#include "myappwindow.h" //使用到我們封裝的 MyAppWindow 提供的接口//利用C語言結構,創建 MyApp 類型, 其父類型為 GtkApplicationstruct _MyApp{ GtkApplication parent;};//同樣定義 MyAppClass 類struct _MyAppClass{ GtkApplicationClass parent_class;};//利用G_DEFINE_TYPE 宏,注冊定義 MyApp 類型 , 對應參數分別代表:類型名 , 小寫類型名(用下劃線分隔) , 父類型G_DEFINE_TYPE ( MyApp , my_app , GTK_TYPE_APPLICATION );//my_app初始化函數原型static void my_app_init (MyApp *app){}//my_app activate 信號原型 , 相當于之前幾節我們手動鏈接的 activate 函數static void my_app_activate (GApplication *app){ MyAppWindow *win; //因此在這里面創建窗口,用我們封裝好的 MyAppWindow win = my_app_window_new ( MY_APP(app) ); //將窗口放在前臺 , 自動調用 gtk_widget_show_all() gtk_window_PResent (GTK_WINDOW(win));}//處理命令行參數的函數原型 static void my_app_open (GApplication *app , GFile **files , gint n_files , const gchar *hint){ GList *windows; MyAppWindow *win; int i; windows = gtk_application_get_windows ( GTK_APPLICATION(app) ); if(windows) win = MY_APP_WINDOW( windows->data ); else win = my_app_window_new ( MY_APP(app) ); for(i = 0; i < n_files; i++) my_app_window_open ( win , files[i] ); gtk_window_present ( GTK_WINDOW(win) );}//MyApp 類的初始化函數,在這里面即可復寫MyApp類繼承GtkAppliation類的默認信號處理函數。static void my_app_class_init ( MyAppClass *class){ //將activate信號和open信號處理函數改為我們寫的 G_APPLICATION_CLASS (class) ->activate = my_app_activate; G_APPLICATION_CLASS (class) ->open = my_app_open;}//這是向外提供的接口,不用加 static 修飾。 MyApp *my_app_new (void){ //按照我們創建的類型創建一個 MyApp return g_object_new ( MY_APP_TYPE , "application-id" , "org.gtk.myapp" , "flags" , G_APPLICATION_HANDLES_OPEN , NULL);}
myapp.h 內容如下:
#ifndef _My_App_H#define _My_App_H#include <gtk/gtk.h>//my_app_get_type() 這些函數,我們雖然沒寫,但是在注冊定義 MyApp 類型的時候根據填寫的 my_app 會自動生成。#define MY_APP_TYPE ( my_app_get_type () )#define MY_APP(obj) ( G_TYPE_CHECK_INSTANCE_CAST( (obj) , MY_APP_TYPE , MyApp) )typedef struct _MyApp MyApp;typedef struct _MyAppClass MyAppClass;//在 myapp.c 中的其他函數屬于私有,暫時不需要向外提供。GType my_app_get_type (void);MyApp *my_app_new (void);#endif // _My_App_
下面封裝MyAppWindow類型的方式和上面一樣,如下是 myappwindow.c
#include <gtk/gtk.h>#include "myapp.h"#include "myappwindow.h"struct _MyAppWindow{ GtkApplicationWindow parent;};struct _MyAppWindowClass{ GtkApplicationWindowClass parent_class;};G_DEFINE_TYPE ( MyAppWindow , my_app_window , GTK_TYPE_APPLICATION_WINDOW);static void my_app_window_init ( MyAppWindow *app){}static void my_app_window_class_init ( MyAppWindowClass *class){ }MyAppWindow *my_app_window_new (MyApp *app){ return g_object_new ( MY_APP_WINDOW_TYPE , "application" , app , NULL); }void my_app_window_open ( MyAppWindow *win , GFile *file){}
以及 myappwindow.h
#ifndef _My_App_Window_H#define _My_App_Window_H#include <gtk/gtk.h>#include "myapp.h"#define MY_APP_WINDOW_TYPE (my_app_window_get_type())#define MY_APP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST( (obj) , MY_APP_WINDOW_TYPE , MyAppWindow) )typedef struct _MyAppWindow MyAppWindow;typedef struct _MyAppWindowClass MyAppWindowClass;GType my_app_window_get_type (void);MyAppWindow *my_app_window_new (MyApp *app);void my_app_window_open (MyAppWindow *win , GFile *file);#endif //_My_App_Window_
編譯并運行:
gcc main.c myapp.c myappwindow.c `pkg-config --cflags --libs gtk+-3.0` -Wall./a.out
運行結果如下:
新聞熱點
疑難解答