gtk, introduction

简介

(GNU image manipulation program)的,现在也用来开发GNOME(GNU Network Object Model Environment),它建立在GDK(GIMP Drawing Kit)的基础上。

弹一个窗口的程序

#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
    GtkWidget *win;

    gtk_init(&argc, &argv);

    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_show(win);

    gtk_main();

    return 0;
}

一下,前面都加了g

了一些默认的设置)

经过窗口管理器的装饰。这里默认的大小是200×200

Hello World

#include <gtk/gtk.h>

void hello(GtkWidget *widget, gpointer data)
{
    g_print("my name is yuanhang zheng\n");
}

gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
    g_print("delete event\n");

    return TRUE;
}

void destroy(GtkWidget *widget, gpointer data)
{
    g_print("destroy\n");
    gtk_main_quit();
}

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(
                         delete_event), NULL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);

    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    button = gtk_button_new_with_label("yuanhang zheng");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(hello), NULL);
    g_signal_connect_swapped(G_OBJECT(button), "clicked",
                         G_CALLBACK(gtk_widget_destroy), G_OBJECT(window));
    gtk_container_add(GTK_CONTAINER(window), button);

    gtk_widget_show(button);
    gtk_widget_show(window);

    gtk_main();

    return 0;
}
gcc -O2 hello.c -lm -o hello `pkg-config --cflags gtk+-2.0` 
`pkg-config --libs gtk+-2.0`

pkg-config是一个小工具,如果系统没有则要安装。 在终端执行下面的命令:

pkg-config --cflags gtk+-2.0

会输出gtk+-2.0程序需要使用到的头文件目录,比如我的是这样的:

-pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include
 -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo
 -I/usr/include/pixman-1 -I/usr/include/libpng15
 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng15
 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz
 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0
 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2

在终端执行下面的命令:

pkg-config --libs gtk+-2.0

会输出gcc编译gtk所需要的库参数,比如我的是这样的:

-lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo
 -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0
 -lglib-2.0 -lfreetype -lfontconfig

调用了gtkmain后,程序会睡眠,等待事件的发生,当有事件(如按下键盘一个键) 发生时,发送者会发送信号,然后执行某一个操作。gsignalconnect的原型为

gulong g_signal_connect(gpointer *object, const gchar *name,
                        GCallback func, gpointer func_data);

其中object为信号的发送者,name为信号的名字,func是回调函数,即要执行的 操作,funcdata是给函数传递的数据。 回调函数的一般原型为:

void callback(GtkWidget *widget, gpointer data);

第一个参数widget为发送信号的widget,第二个参数data为传递过来的数据。 我刚开始对gsignalconnectswapped函数有很多疑问,看了书上的说法,终于 明白了,它和gsignalconnect的作用几乎一样,只是它的回调函数只接收一个 参数,如:

void callback(GtkObject *object);

因为gtk里面的很多库函数没有传送数据,所以才出现了这个东西专门用来回调那些 不传递数据的函数。

g_signal_connect(G_OBJECT(button), "button_press_event",
                 G_CALLBACK(button_press_callback), NULL);
static gint button_press_callback(GtkWidget *widget,
                                  GdkEventButton *event,
                                  gpointer data);

可以通过上面这种方式使用回调函数。 GdkEvent是一个联合体,是很多事件的名字的集合。

深入探索Hello World

FALSE,则会关闭窗口。

再绑定gtkwidgetdestroy,因为没有数据传递,所以使用了gsignalconnectswapped 函数,最后一个参数表明这个按钮button是放在window上面的。

先弹出窗口,再显示按钮这种奇怪的事情了。

#include <gtk/gtk.h>

void hello(GtkWidget *widget, gpointer data)
{
    g_print("%s\n", (gchar *)data);
}

gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
    gtk_main_quit();

    return FALSE;
}

void destroy(GtkWidget *widget, gpointer data)
{
    gtk_main_quit();
}

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "yuanhang");
    gtk_container_set_border_width(GTK_CONTAINER(window), 20);
    g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(
                         delete_event), NULL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);

    box = gtk_hbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), box);

    button = gtk_button_new_with_label("one");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(hello),
                     (gpointer)"one");
    gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
    gtk_widget_show(button);

    button = gtk_button_new_with_label("two");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(hello),
                     (gpointer)"two");
    gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);
    gtk_widget_show(button);

    gtk_widget_show(box);
    gtk_widget_show(window);

    gtk_main();

    return 0;
}

这里加了一个box,把2个button加到box里面,传递回调函数的数据时,传了一个字符串, 在回调函数里面把这个字符串打印出来。