Linux 下从头再走 GTK+-3.0 (六)

  在 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 类型, 其父类型为 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 内容如下:

#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

  运行结果如下:

时间: 2024-10-08 13:17:52

Linux 下从头再走 GTK+-3.0 (六)的相关文章

Linux 下从头再走 GTK+-3.0 (一)

原本由于项目需求在 Linux 下学习过一段时间的 GTK+2.0 图形开发,时隔一段时间,想真正深入学习一下 GTK . 这次直接从头学习 GTK+-3.0 ,并写下博文便于日后查看,也方便新手入门. 安装环境参考: Fedora:http://www.cnblogs.com/watsonlong/archive/2011/04/06/2006989.html Ubuntu:http://www.cnblogs.com/niocai/archive/2011/07/15/2107472.htm

Linux 下从头再走 GTK+-3.0 (三)

之前我们为窗口添加了一个按钮,接下来让这个按钮丰富一点.并给窗口加上图标. 首先创建 example3,c 的源文件. #include <gtk/gtk.h> static void activate(GtkApplication *app , gpointer data); //从文件中加载一张图片 GdkPixbuf *create_pixbuf(const char *image_name); int main(int argc , char **argv) { GtkApplicat

Linux 下从头再走 GTK+-3.0 (二)

仅仅创建一个空白窗口是不够的,下面我们为创建的窗口添加一个按钮. 以 Hello,World!为例. 首先创建一个源文件:example2.c 内容如下. #include <gtk/gtk.h> //点击按钮后被调用的函数,用于输出hello,world static void print_msg (GtkWidget *button , gpointer data) { printf("Hello , world!\n"); } static void activate

Redhat linux下安装oracle11r2手册+截图_toto_V1.0

 在Linux下安装配置Oracle 11g R2详细过程(在整个过程中是在虚拟机下模拟的,虚拟机磁盘设置成了100GB) 1.Linux环境配置准备 环境:Linux:Redhat Enterprise 6,DB:Oracle 11gR2 X64,Oracle安装到/home/oralce_11目录下. 配置过程如下:(大部分是网上的内容,个人也是按照网上步骤来的) 1) 检查基本需求(对于牛逼的服务器来说,这个肯定是满足要求的,可以跳过) 内存大小 grep MemTotal /proc

Linux下安装二进制版mysql-8.0.15

1.添加用户## 添加用户组groupadd mysql## 添加用户,指定用户home目录useradd -g mysql mysql -d /data/mysql## 解压下载的mysql二进制包tar -xvf mysql-8.0.15-linux-glibc2.12-x86_64.tar.xz -C /data/mysql## 如果需要修改目录名称,mv修改目录名称,不多说明## 因/data目录有比较大的磁盘空间,防止后期数据量太大,导致磁盘空间不够,将mysql的包及相关配置放在/d

linux下如何编译安装gcc-8.3.0

1. 获取源码 wget https://mirrors.ustc.edu.cn/gnu/gcc/gcc-8.3.0/gcc-8.3.0.tar.xz -P ~ tar xvf gcc-8.3.0.tar.xz -C ~ cd ~/gcc-8.3.0 2. 运行 download_prerequisites 脚本 ./contrib/download_prerequisites 3. 创建编译目录 mkdir build-gcc-8.3.0 cd build-gcc-8.3.0 4. 配置 ..

如何实现Linux下的U盘(USB Mass Storage)驱动

摘要 本文主要介绍了USB Mass Storage的相关的各种协议之间的关系,以及如何在Linux的USB驱动框架下实现U盘驱动 本文提供多种格式供: 在线阅读 HTML HTMLs PDF CHM TXT RTF 下载(7zip压缩包) HTML HTMLs PDF CHM TXT RTF HTML版本的在线地址为: http://www.crifan.com/files/doc/docbook/usb_disk_driver/release/html/usb_disk_driver.htm

linux 下 select 编程

linux 下的 select 知识点 unp 的第六章已经描述的很清楚,我们这里简单的说下 select 的作用,并给出 select 的客户端实例.我们知道 select 是IO 多路复用的一个最简单支持,poll 和 epoll 是 select 的升级版.在 UNIX 网络编程第五章读书笔记 我们遇到这样一个问题:当客户端阻塞在 fgets() 等待客户输入的时候,服务器端断开连接.而客户端却不能及时知道,只有在客户输入完毕并发送到服务器的时候才知道连接已经断开,但是此时可能已经过了很长

实现Linux下的U盘(USB Mass Storage)驱动

如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write Linux USB MSC (Mass Storage Class) Driver Crifan Li 摘要 本文主要介绍了USB Mass Storage的相关的各种协议之间的关系,以及如何在Linux的USB驱动框架下实现U盘驱动 本文提供多种格式供: 在线阅读 HTML HTMLs PDF CHM TXT RTF WEBHELP 下载(7zip压缩包) HTML HTMLs PDF