【GTK+ 3】第一个程序

写在前面的话:

  1. 版权声明:本文为博主原创文章,转载请注明出处!
  2. 博主是一个小菜鸟,并且非常玻璃心!如果文中有什么问题,请友好地指出来,博主查证后会进行更正,啾咪~~
  3. 每篇文章都是博主现阶段的理解,如果理解的更深入的话,博主会不定时更新文章。
  4. 本文初次更新时间:2020.8.6,最后更新时间:2020.10.23

前言

网上有太多 GTK+ 2 的教程了,看了一下 GTK+ 已经出到4了,综合一下打算写一下 GTK+ 3。

有兴趣的话也可以自己查看官方手册:

正文开始

创建一个200 × 200像素的空窗口

运行效果如图:
200×200空窗口

源代码

代码文件demo.c

#include <gtk/gtk.h>

static void activate (GtkApplication* app, gpointer user_data)
{
    GtkWidget *window;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
    gtk_widget_show_all (window);
}

int main (int argc, char **argv)
{
    GtkApplication *app;
    int status;

    app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);

    return status;
}

编译指令

gcc `pkg-config --cflags gtk+-3.0` -o demo demo.c `pkg-config --libs gtk+-3.0`

代码解析

GTK+头文件:gtk/gtk.h

main() 函数

main() 函数的作用是创建GtkApplication对象并运行它。

int main (int argc, char **argv)
{
    GtkApplication *app;
    int status;

    app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);  //创建GtkApplication对象
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);

    return status;
}
gtk_application_new()
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);

GtkApplication是 Application 类。gtk_application_new()用于创建GtkApplication实例。

GtkApplication *
gtk_application_new (const gchar *application_id,
                     GApplicationFlags flags);

该函数文档可以点这里

  • 参数application_id:应用程序标识符(名称),GTK+ 3.6或更高版本允许使用null,该参数详情看这里
  • 参数flags:应用程序标志。
  • 返回值:返回一个新的GtkApplication实例。
g_signal_connect()
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

这里将激活信号连接到activate()函数。

#define g_signal_connect(instance, detailed_signal, c_handler, data)
  • 参数instance:连接的实例
  • 参数detailed_signal:字符串,详细信号,看下面信号详情。
  • 参数c_handler:连接的回调函数
  • 参数data:数据传递给c_handler调用
  • 返回值:Gulong 类型的处理程序 ID (成功连接时总是大于0)

GtkApplication的一组应用程序应该响应的信号

  1. startup:在应用程序第一次启动时设置
  2. shutdown:执行关闭任务
  3. activate:显示应用程序的默认第一个窗口,对应于桌面环境正在启动的应用程序。
  4. open:打开文件并在新窗口中显示它们,对应于有人试图从文件浏览器或类似的应用程序打开文档。

当应用程序启动时,将触发startup信号,可以执行一些初始化任务。之后,根据应用程序的启动方式,接下来将调用 activateopen
GtkApplication 默认将应用程序设为单实例。如果用户尝试启动第二个实例,则GtkApplication 将向第一个实例发出信号,你将收到其他activateopen信号。在这种情况下,第二个实例将立即退出,而不调用 startupshutdown
在关闭任务时,将会收到一个shutdown信号,可以执行一些清理任务(例如将文件保存到磁盘)。

文档指出,main() 函数应该尽可能小,除了创建和运行 GtkApplication 之外几乎什么都不做。真正的工作应该始终根据 GtkApplication 触发的信号来完成。

g_application_run()
status = g_application_run (G_APPLICATION (app), argc, argv);

当应用程序运行g_application_run()启动时,将发送activate信号。gtk_application_run()还将指向命令行参数计数器和字符串数组的指针作为参数; 这使GTK+可以解析控制GTK+本身行为的特定命令行参数。解析后的参数将从数组中删除,将无法识别的参数留给应用程序解析。

int
g_application_run (GApplication *application,
                   int argc,
                   char **argv);

运行应用程序。该函数详情可以点这里

  • 参数application:应用程序
  • 参数argcmain()中的argc(如果argvNULL,则为0
  • 参数argvmain()中的argv,或NULL
  • 返回值:exit 的状态
g_object_unref()
g_object_unref (app);

使用g_object_unref()从内存中释放GtkApplication对象。

void
g_object_unref (gpointer object);
activate() 函数
static void activate (GtkApplication* app, gpointer user_data)
{
    GtkWidget *window;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
    gtk_widget_show_all (window);
}

当应用程序运行g_application_run()启动时,将发送activate信号,该信号发送后,将进入应用程序的activate()函数。在该函数内部,要构造GTK窗口,以便在启动应用程序时显示一个窗口。

gtk_application_window_new()
GtkWidget *window;
window = gtk_application_window_new (app);

调用gtk_application_window_new()将创建一个新的GtkWindow并将其存储在window指针中。

GtkWidget *
gtk_application_window_new (GtkApplication *application);

创建一个新的GtkWindow。

gtk_window_set_title()
gtk_window_set_title (GTK_WINDOW (window), "Window");

使用gtk_window_set_title()设置窗口标题

void
gtk_window_set_title (GtkWindow *window,
                      const gchar *title);
  • 参数window:一个 GtkWindow
  • 参数title:窗口的标题

此函数将GtkWindow*字符串作为输入。由于window指针是GtkWidget*,因此需要将其强制转换为GtkWindow*,但不是用 (GtkWindow*)强制执行window转换, 而是使用宏GTK_WINDOW()

GTK_WINDOW()会在强制转换之前检查指针是否为GtkWindow类的实例,并在检查失败时发出警告。有关此约定的更多信息,请参见此处

gtk_window_set_default_size()
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

该函数用于设置窗口大小。

void
gtk_window_set_default_size (GtkWindow *window,
                             gint width,
                             gint height);

设置窗口的默认大小。该函数详情可以点这里

  • 参数window:一个 GtkWindow
  • 参数width:宽度(单位:像素),或者-1来取消默认宽度
  • 参数height:高度(单位:像素),或者-1来取消默认高度
gtk_widget_show_all()
gtk_widget_show_all (window);

通过gtk_widget_show_all()来显示窗口。

void
gtk_widget_show_all (GtkWidget *widget);

递归地显示一个小部件和小部件里的所有子小部件。

创建一个有按钮的窗口

运行效果如图:
Hello World

源代码

该代码是在上面的demo.c的基础上改的,在窗口增加了按钮,按钮标签为Hello World

#include <gtk/gtk.h>

static void print_hello (GtkWidget *widget, gpointer   data)
{
    g_print ("Hello World\n");
}

static void activate (GtkApplication *app, gpointer user_data)
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *button_box;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

    button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_container_add (GTK_CONTAINER (window), button_box);

    button = gtk_button_new_with_label ("Hello World");
    g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
    g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
    gtk_container_add (GTK_CONTAINER (button_box), button);

    gtk_widget_show_all (window);
}

int main (int argc, char **argv)
{
    GtkApplication *app;
    int status;

    app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);

    return status;
}

代码解析

这里main()函数同上。

activate()
static void activate (GtkApplication *app, gpointer user_data)
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *button_box;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

    button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
    gtk_container_add (GTK_CONTAINER (window), button_box);

    button = gtk_button_new_with_label ("Hello World");
    g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
    g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
    gtk_container_add (GTK_CONTAINER (button_box), button);

    gtk_widget_show_all (window);
}

看一下activate()函数不同的部分:

声明了buttonbutton_box两个新的GtkWidget指针来实现。

button_box变量用于存储GtkButtonBox。GtkButtonBox是GTK+控制按钮的大小和布局的方式,即用来排列按钮的容器。

gtk_button_box_new()
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);

gtk_button_box_new()用于创建一个新的GtkButtonBox

GtkWidget *
gtk_button_box_new (GtkOrientation orientation);
  • 参数orientation:盒子的朝向,GtkOrientation枚举,即该盒子包含的按钮是水平方式或垂直方式存储。

在这里只处理一个按钮,所以方向无所谓。

gtk_container_add()
gtk_container_add (GTK_CONTAINER (window), button_box);

在初始化button_box之后,使用gtk_container_add()将button_box小部件添加到窗口小部件中。

这里,对应关系如下:
window内部对应关系
未完待续~~

参考

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值