环境准备
官网下载 GTK 源码包,因为本机 GLib 版本不够,下载一个非最新版的 GTK3.8.0 先学习用
直接阅读 "/gtk+-3.8.0/docs/reference/gtk/html/gtk-building.html" 进行操作
安装完毕,gtk3-demo
出来 gtk 的样例界面即安装搞定
实例学习
编译命令和编译脚本
编译参数包括 pkg-config --libs --cflags gtk+-3.0
为了方便,用脚本管理起来
build.sh
#!/bin/bash if [ $# -lt 1 ]; then echo "usage: $0 [xxxx.c]" exit fi gcc -o $1_out $1 `pkg-config --libs --cflags gtk+-3.0`
一个简单的HelloWorld按钮
01_simple_button.c
#include <gtk/gtk.h> // 回调函数1 void hello( GtkWidget *widget, GdkEvent *event, gpointer data ) { g_print("Hello World\n"); } // 回调函数2 void destroy( GtkWidget *widget, gpointer data ) { gtk_main_quit(); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /** * 如果 "delete_event" 信号处理函数 * 返回 FALSE,GTK 会发出 "destroy" 信号 * 返回 TRUE,你不希望关闭窗口 * 当希望弹出 "你确定要退出吗?" 对话框时可以用到 */ g_print("delete event occurred\n"); return FALSE; } int main( int argc, char *argv[] ) { // GtkWidget 是构件的存储类型 GtkWidget *window; GtkWidget *button; /** * gtk_init 函数在所有的 GTK 程序都要调用 * 参数由命令行中解析出并填充进来 */ gtk_init( &argc, &argv ); window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); /** * 当窗口收到 "delete_event" 信号(该信号由窗口管理器发出, * 通常是"关闭"选项或是标题栏上的关闭按钮发出的) * 我们让其调用在前面定义的 delete_event 函数 * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略 */ g_signal_connect( G_OBJECT( window ), "delete_event", G_CALLBACK( delete_event ), NULL ); /** * 连接 "destroy" 事件到一个信号处理函数,对该窗口调用 * gtk_widget_destroy 函数或在 "delete_event" 回调函数 * 中返回 FALSE 值都会触发该事件 */ g_signal_connect( G_OBJECT( window ), "destroy", G_CALLBACK( destroy ), NULL ); // 设置窗口边框的宽度 gtk_container_set_border_width ( GTK_CONTAINER(window), 10 ); // 创建一个标签为 Hello World 的新按钮 button = gtk_button_new_with_label( "Hello World" ); // 当按钮触发 "clicked" 事件时,会调用回调函数 hello g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( hello ), "1" ); // 当按钮触发 "clicked" 事件时,调用 gtk_widget_destroy(window) // 来关闭窗口,"destroy" 信号会从这里或从窗口管理器发出 // g_signal_connect_swapped (G_OBJECT (button), "clicked", // G_CALLBACK (gtk_widget_destroy),window); // 把按钮放入窗口(一个gtk容器)中 gtk_container_add ( GTK_CONTAINER( window), button ); // 显示新创建的按钮和窗口 gtk_widget_show( button ); gtk_widget_show( window ); // 程序运行停在这里等待事件的发生(如键盘事件/鼠标事件) gtk_main(); return 0; }
两个按钮
02_two_buttons.c
#include <gtk/gtk.h> // 改进回调函数,传递到该函数的数据将打印到标准输出中(stdout) void callback( GtkWidget *widget, gpointer data ) { g_print( "%s", (gchar *) data ); } // 回调函数2 gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { gtk_main_quit(); return FALSE; } int main( int argc, char *argv[] ) { GtkWidget *window; GtkWidget *button; GtkWidget *box1; gtk_init( &argc, &argv ); window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); // 设置窗口标题 gtk_window_set_title( GTK_WINDOW( window ), "Hello Buttons!" ); g_signal_connect( G_OBJECT( window ), "delete_event", G_CALLBACK( delete_event ), NULL ); gtk_container_set_border_width( GTK_CONTAINER( window ), 20 ); // 创建一个组装盒,组装盒非可见,它仅被作为排列构件的工具 box1 = gtk_hbox_new( FALSE, 1 ); // 把组装盒放入主窗口中 gtk_container_add ( GTK_CONTAINER( window ), box1 ); button = gtk_button_new_with_label( "Hello" ); g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "hello"); // 代替 gtk_container_add, 把按钮放入组装盒中, 组装盒已经放入窗口中了 gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 ); gtk_widget_show( button ); button = gtk_button_new_with_label( "World" ); g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "World"); gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 ); gtk_widget_show( button ); button = gtk_button_new_with_label( "!" ); g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "!"); gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 ); gtk_widget_show( button ); gtk_widget_show( box1 ); gtk_widget_show( window ); gtk_main(); return 0; }
一图片和一按钮
03_image_and_button.c
#include "gtk/gtk.h" int main( int argc, char *argv[] ) { GtkWidget* window; GtkWidget* vbox; GtkWidget* image; GtkWidget* button; gtk_init( &argc, &argv ); window = gtk_window_new( GTK_WINDOW_POPUP ); gtk_window_set_title( GTK_WINDOW(window), "Splash窗口" ); g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL ); // 设置窗口处于屏幕中央 gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_CENTER ); // gtk_container_set_border_width( GTK_CONTAINER(window), 20 ); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add( GTK_CONTAINER(window), vbox ); image = gtk_image_new_from_file("gnome-desktop.png"); gtk_box_pack_start( GTK_BOX(vbox), image, FALSE, FALSE, 0 ); button = gtk_button_new_with_label( "Splash窗口" ); g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_main_quit ), NULL ); gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 ); gtk_widget_show_all( window ); gtk_main(); return FALSE; }
可前进后退的提示窗口
04_notify_window.c
#include <gtk/gtk.h> // XPM格式图像数据 static char * book_open_xml[] = { "16 16 4 1", " c None s None", ". c black", "X c #808080", "o c white", " ", " .. ", " .Xo. ... ", " .Xoo. ..oo. ", " .Xooo.Xooo... ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xoo.Xoo..X. ", " .Xo.o..ooX. ", " .X..XXXXX. ", " ..X....... ", " .. ", " " }; // 自定义提示 static gchar *info[5] = { "此软件用于测试每日提示功能的实现,如果你发现问题请及时回复。", "我们的目的是把GTK+2.0的大多数功能奉献给每一位自由软件爱好者和开发者。", "每一位Linux的支持者都会让我们增加一分信心,Linux最终仍是台式计算机操作系统。", "计算机软件技术是一种科学技术,它和人类历史上其他的科学技术一样,是允许每一人自由使用的。", "当前你测试完此程序后,请设法把它附加到你创作的软件当中去,这是你成功的第一步。" }; static GtkWidget *window; // 主窗口 static GtkWidget *frame; // 框架 static GtkWidget *pre_button; // 上一提示按钮 static GtkWidget *next_button; // 下一提示按钮 static GtkWidget *label; // 提示信息内容标签 static GtkWidget *title; // 框架标题 gint current_info = 0; // 当前提示信息计数 // 创建框架控件标题 GtkWidget* create_title( GtkWidget *data ) { GtkWindow *title; GtkWindow *hbox; GtkWindow *image; GtkWindow *label; GtkWindow *pixmap; GtkWindow *mask; GdkWindow *window; pixmap = gdk_pixbuf_new_from_xpm_data ( book_open_xml ); image = gtk_image_new_from_pixbuf( pixmap ); label = gtk_label_new( "新的标题" ); hbox = gtk_hbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 2 ); gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 2 ); return hbox; } GtkWidget* create_button( gchar* stockid, gchar* title ) { GtkWidget *button; GtkWidget *image; GtkWidget *label; GtkWidget *hbox; image = gtk_image_new_from_stock( stockid, GTK_ICON_SIZE_MENU ); label = gtk_label_new( title ); hbox = gtk_hbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 3 ); gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 3 ); button = gtk_button_new(); gtk_container_add( GTK_CONTAINER(button), hbox ); return button; } // 上一提示 void pre_info( GtkButton *button, gpointer data ) { gint i; i = current_info - 1; if (i == -1 ) return; if (i == 0 ) gtk_widget_set_sensitive( pre_button, FALSE ); current_info = i; gtk_widget_set_sensitive( next_button, TRUE ); gtk_label_set_text( GTK_LABEL( label ), info[current_info] ); } // 下一提示 void next_info( GtkButton *button, gpointer data ) { gint i; i = current_info + 1; if (i == 5 ) return; if (i == 4 ) gtk_widget_set_sensitive( next_button, FALSE ); current_info = i; gtk_widget_set_sensitive( pre_button, TRUE ); gtk_label_set_text( GTK_LABEL( label ), info[current_info] ); } int main( int argc, char* argv[] ) { GtkWidget *hbox; GtkWidget *vbox; GtkWidget *bbox; GtkWidget *button; GtkWidget *image; GtkWidget *title; gtk_init( &argc, &argv ); window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); g_signal_connect( G_OBJECT( window ), "delete_event", G_CALLBACK( gtk_main_quit ), NULL ); gtk_window_set_title( GTK_WINDOW( window ), "每日提示" ); gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_CENTER ); gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); gtk_widget_realize( window ); vbox = gtk_vbox_new( FALSE, 0 ); gtk_container_add( GTK_CONTAINER( window ), vbox ); hbox = gtk_hbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 5 ); image = gtk_image_new_from_file( "gnome-desktop.png" ); gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 5 ); frame = gtk_frame_new( NULL ); title = create_title( window ); gtk_frame_set_label_widget( GTK_FRAME( frame ), title ); gtk_box_pack_start( GTK_BOX( hbox ), frame, TRUE, TRUE, 5 ); label = gtk_label_new( NULL ); gtk_label_set_text( GTK_LABEL( label ), info[0] ); gtk_label_set_line_wrap( GTK_LABEL( label ), TRUE ); gtk_container_add( GTK_CONTAINER( frame ), label ); bbox = gtk_hbutton_box_new(); gtk_button_box_set_layout( GTK_BUTTON_BOX( bbox ), GTK_BUTTONBOX_END ); gtk_box_pack_start( GTK_BOX( vbox ), bbox, FALSE, FALSE, 5 ); button = gtk_check_button_new_with_label( "每次启动时显示" ); gtk_box_pack_start( GTK_BOX( bbox ), button, FALSE, FALSE, 5 ); pre_button = create_button( GTK_STOCK_GO_BACK, "上一提示" ); gtk_widget_set_sensitive ( pre_button, FALSE ); g_signal_connect( G_OBJECT( pre_button ), "clicked", G_CALLBACK( pre_info ), NULL ); gtk_box_pack_start( GTK_BOX( bbox ), pre_button, FALSE, FALSE, 5 ); next_button = create_button( GTK_STOCK_GO_FORWARD, "下一提示" ); g_signal_connect( G_OBJECT( next_button ), "clicked", G_CALLBACK( next_info ), NULL ); gtk_box_pack_start( GTK_BOX( bbox ), next_button, FALSE, FALSE, 5 ); button = gtk_button_new_from_stock( GTK_STOCK_OK ); g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_main_quit ), NULL ); gtk_box_pack_start( GTK_BOX( bbox ), button, FALSE, FALSE, 5 ); gtk_widget_show_all( window ); gtk_main(); return FALSE; }
... 后面有空继续更新
总结
gtk+ 现有资料已经很少了, 属于淘汰型技术了, 勿深究.
来源:https://www.cnblogs.com/hencins/p/12204099.html