gtk, introduction
文章目录
简介
- GTK(GIMP ToolKit),是用于构建GUI的库来的。取这个名字,是因为GTK是用于开发GIMP
(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;
}
- 所有的程序都要使用<gtk/gtk.h>这个头文件。
- gtk~init~(gint *argc, gchar ***argv),原来这个库把基本的类型都重新定义了
一下,前面都加了g
- gtk~init这个函数~,设置了一些基本的东西(比如默认的可视化界面,颜色图等,初始化
了一些默认的设置)
- gtk~windownew函数用于创建窗口~,GTK~WINDOWTOPLEVEL参数表示我们想让这个窗口~
经过窗口管理器的装饰。这里默认的大小是200×200
- gtk~widgetshow用于显示窗口~
- gtk~main用于进入gtk的主函数循环~,在这个循环里,程序会一直等待事件的产生。
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
- 有关这些库的说明:
- -lgtk,是GTK的库,主要是widget的库
- -lgdk,是GDK的库,主要是Xlib的wrapper
- -lgdk~pixbuf~,是gdk~pixbuf的库~,主要包含了图像处理的操作
- -lpango,是Pango库,用于国际化,即对各国语言的支持
- -lgobject,是gobject库,包含了gtk里面的类型系统
- -lgmodule,是gmodule库,用于加载运行时的扩展
- -lglib, 是GLib库,包含了一些乱七八糟的函数,比如g~print~
- -lX11,是Xlib库,GDK需要用到
- -lXext,是Xext库,包含了共享内存的pixmap的代码和其它的X扩展
- -lm,这个不用说,是数学函数库
- 有关信号signal的概念
调用了gtk~main后~,程序会睡眠,等待事件的发生,当有事件(如按下键盘一个键) 发生时,发送者会发送信号,然后执行某一个操作。g~signalconnect的原型为~:
gulong g_signal_connect(gpointer *object, const gchar *name,
GCallback func, gpointer func_data);
其中object为信号的发送者,name为信号的名字,func是回调函数,即要执行的 操作,func~data是给函数传递的数据~。 回调函数的一般原型为:
void callback(GtkWidget *widget, gpointer data);
第一个参数widget为发送信号的widget,第二个参数data为传递过来的数据。 我刚开始对g~signalconnectswapped函数有很多疑问~,看了书上的说法,终于 明白了,它和g~signalconnect的作用几乎一样~,只是它的回调函数只接收一个 参数,如:
void callback(GtkObject *object);
因为gtk里面的很多库函数没有传送数据,所以才出现了这个东西专门用来回调那些 不传递数据的函数。
- 有关事件event的概念
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
- delete~event函数~,返回TRUE表示,不产生destroy信号,窗口不会关闭,如果返回
FALSE,则会关闭窗口。
- G~OBJECT和GCALLBACK是用来强制转换类型并检查类型的宏~。
- 一个widget可以绑定多个回调函数,按照绑定的顺序来触发,这里,先绑定hello函数,
再绑定gtk~widgetdestroy~,因为没有数据传递,所以使用了g~signalconnectswapped~ 函数,最后一个参数表明这个按钮button是放在window上面的。
- gtk~widgetshow的顺序要注意~,先把button显示,再显示window,这样就不会出现
先弹出窗口,再显示按钮这种奇怪的事情了。
- gtk的设计是面向对象的。
- 修改过的hello world
#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里面,传递回调函数的数据时,传了一个字符串, 在回调函数里面把这个字符串打印出来。