在 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 内容如下:
代码语言:javascript复制#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
代码语言:javascript复制#include <gtk/gtk.h>
#include "myapp.h"
#include "myappwindow.h" //使用到我们封装的 MyAppWindow 提供的接口
//利用C语言结构,创建 MyApp 类型, 其父类型为 GtkApplication
struct _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 内容如下:
代码语言:javascript复制#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
代码语言:javascript复制#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
代码语言:javascript复制#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_
编译并运行:
代码语言:javascript复制gcc main.c myapp.c myappwindow.c `pkg-config --cflags --libs gtk -3.0` -Wall
./a.out
运行结果如下: