转载请注明:http://blog.csdn.net/hubbybob1/article/details/49159581
本文主要是针对 –GTK+2.0编程范例–宋国伟老师的书内的代码做一些注释,兼并讨论一下GTK+3.0与2.0的区别.其安装,在网上有很多讲解.
第1章 窗口与简单控件
1.1最简单的窗口
程序如下base.c
/*simple windows_base.c*/
#include <gtk/gtk.h>
int main(int argc,char*argv[])
{
GtkWidget *window;//定义window控件
gtk_init(&argc,&argv);//这句话是必须有的,初始化命令行参数
//创建window控件,参数GTK_WINDOW_TOPLEVEL:窗口类型,为最上层主窗口,GTK_WINDOW_TOPLEVEL:弹出式无边框窗口
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(window);//创建后显示控件
gtk_main();//这句话必须要,没有为什么,最关键,主事件循环
return 0;
}
下面是Makefile文件
CC=gcc
all:
$(CC) -o base base.c `pkg-config --cflags --libs gtk+-2.0`
pkg-config –cflags –libs gtk+-2.0是指的向编译器指出包含文件的路径,动态链接库路径和要链接的动态链接库.此处的2.0可以换成3.0.执行make后运行base]文件如下:
1.2完善窗口功能
程序如下window.c
#include <gtk/gtk.h>
int main(int argc, char* argv[])
{
GtkWidget *window;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);//GTK_WINDOW_POPUP创建窗口
// g_signal_connect函数为glib函数包含四个参数
//1:为链接的对象就是G_OBJECT,
//2:信号名称,字符串形式,不同控件有不同信号,名称也不一样
//3:回调函数,要使用G_CALLBACK来调用
//4:传递个回调函数的参数,类型为gpointer,如果不是这个类型就强制转换,没有参数就是NULL
//gtk_main_quit函数:退出主循环,就是借宿程序
g_signal_connect(G_OBJECT(window),"delete_evernt",G_CALLBACK(gtk_main_quit),NULL);
gtk_window_set_title(GTK_WINDOW(window),"一个完整的窗口");//设定窗口标题
gtk_window_set_default_size(GTK_WINDOW(window),500,100);//设置窗口默认大小
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
//设置窗口位置:
//GTK_WIN_POS_CENTER 居中
//GTK_WIN_POS_NONE 不固定
//GTK_WIN_POS_MOUSE 出现在鼠标位置
//GTK_WIN_POS_CENTER_ALWAYS 窗口改变尺寸仍然居中
//GTK_WIN_POS_CENTER_PARENT 居于父窗口中部
gtk_widget_show(window);
gtk_main();
return FALSE;
}
其Makefile为:
CC = gcc
all:
$(CC) -o window window.c `pkg-config --cflags --libs gtk+-2.0`
运行window后得到
1.3hello程序
程序hello.c如下:
//hello.c
#include <gtk/gtk.h>
gint count = 1;
void on_button_click(GtkWidget *button, gpointer userdata)// GtkWidget *button, int *userdata
{
g_print("你好,这是hello功能的测试");
g_print("%d %d\n",(gint)userdata,count);//添加了count项
count = count + 1;
}
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(gtk_main_quit),NULL);//回调函数为gtk_main_quit
gtk_window_set_title(GTK_WINDOW(window),"hello test");
gtk_window_set_default_size(GTK_WINDOW(window),500,100);
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
gtk_container_set_border_width(GTK_CONTAINER(window),60);
//创建按钮
button = gtk_button_new_with_label("按下此按钮会在终端显示信息");
//为button添加一个回调函数为on_button_click,传入回调函数的参数为(gpointer)count
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(on_button_click),(gpointer)count);//(gpointer)count (int)&(count)
gtk_container_add(GTK_CONTAINER(window),button);//把按钮加入窗口
gtk_widget_show(button);//显示按钮 ,这两个显示的顺序可以调换
gtk_widget_show(window);//显示窗口
gtk_main();
return FALSE;
}//其Makefile如下:
CC = gcc
all:
$(CC) -o hello hello.c `pkg-config --cflags --libs gtk+-2.0`
其显示的结果如下:
当按下按钮是产生的结果是,在终端打印出一下结果:
这个结果令我很失望,并不是书中所说的后面的回调函数执行后的值不断+1,而count却是不断加大的,这是为什么?我们来修改一些看看是什么样子:
/*把on_button_click回调函数修改为如下:参数gpointer userdata变为int *userdata*/
void on_button_click(GtkWidget *button, int *userdata)// GtkWidget *button, gpointer userdata
{
g_print("你好,这是hello功能的测试");
i=*userdata;
g_print("%d %d\n",i,count);
count = count + 1;
}
执行的结果为出现段错误:
那么继续修改主程序:
//g_signal_connect(G_OBJECT(button),"clicked",
// G_CALLBACK(on_button_click),(gpointer)count);//(gpointer)count (gint)&(count)
//把按钮回调函数修改为如下,把参数改为(gint)&(count)
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(on_button_click),(gint)&(count));//(gpointer)count (gint)&(count)
那么来编译一下,会出现如下提示:
就是说g_signal_connect的第四个参数需要gpointer指针,而我们传的却是int,但是没有报错,不管了直接运行,点击按钮看看结果如何:
可见无论是count的值,还是回调函数传过来的值都是变化的,那就改问了这是为什么呢,是BUG吗?,这个小编也不知道怎么回事,只能在以后的代码测试中来验证了.
1.4用盒状容器来排列按钮
程序pack.c如下:
/*容器主要包括:盒状容器(GtkBox),格状容器(GtkTable),按钮盒(GtkButtonBox),分割面板(GtkPanel),固定布局(GtkFixed),工具栏(GtkToolbar)等*/
/*用盒状容器排列按钮*/
#include <gtk/gtk.h>
int main(int argc,char* argv[])
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *box;//创建盒状容器
gchar *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),title);//设置窗口标题
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);//设置窗口位置
gtk_container_set_border_width(GTK_CONTAINER(window),20);
//创建横向盒状容器
//gtk_vbox_new(FALSE,0),这是创建竖向的,
//第一个参数为是否均匀排放,FALSE:不均匀,有大有小,第二个参数表示容器中控件的间隔
box = gtk_hbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window),box);//向window 内添加此容器
/**************************************************************
1,把创建的button加入到容器内,可使用两种方法:使用gtk_container_add,但只能加1个控件,你可以下面的gtk_box_pack_start,换成gtk_box_pack_start,试试看,其实没什么变化,只是一些参数无法使用例如按钮间隔参数
2,使用gtk_box_pack_*系列函数,这也有两种方法
A.使用gtk_box_pack_start/gtk_box_pack_end,表示按顺序从前到后或者从后到前排列,含有5个参数
容器GTK_BOX(box),
控件对象指针button
是否可扩展(就是横向是否可扩展,当横向拉大窗口时,其相对位置宽度都发生变化,当FASE就不变化,TRUE就变化)
是否填充
与前一控件的间隔
B.使用gtk_box_pack_start_default/gtk_box_pack_end_default,只有两个参数,其他值都是默认
但可以使用gtk_box_set_homogeneous/gtk_box_get_homogeneous设置/获得是否允许均匀排放
可以使用gtk_box_set_spacing/gtk_box_get_spacing来设置/获得子空间之间的间隔
***************************************************************/
button = gtk_button_new_with_label("按钮一");//创建button
gtk_box_pack_start(GTK_BOX(box),button,TRUE,TRUE,3);
//gtk_container_add(GTK_CONTAINER(box),button);
button = gtk_button_new_with_label("按");
gtk_box_pack_start(GTK_BOX(box),button,FALSE,FALSE,3);
//gtk_container_add(GTK_CONTAINER(box),button);
button = gtk_button_new_with_label("钮");
gtk_box_pack_start(GTK_BOX(box),button,FALSE,FALSE,3);
//gtk_container_add(GTK_CONTAINER(box),button);
button = gtk_button_new_with_label("二");
//gtk_container_add(GTK_CONTAINER(box),button);
gtk_widget_show_all(window);//把六个gtk_widget_show()函数节省为1行,1个窗口,1个盒装容器,4个按钮
gtk_main();
return FALSE;
}//下面是Makefile
CC = gcc
all:
$(CC) -o pack pack.c `pkg-config --cflags --libs gtk+-2.0`
1.5用格状容器来排列按钮
程序table.c如下:
/*格状容器 table.c*/
#include<gtk/gtk.h>
int main(int argc,char* argv[])
{
GtkWidget * window;
GtkWidget *table;
GtkWidget *button;
GtkWidget *frame;
gtk_init(&argc,&argv);
//创建窗口
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"格状容器");
gtk_window_set_default_size(GTK_WINDOW(window),200,300);
g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL);
gtk_container_set_border_width(GTK_CONTAINER(window),20);
//创建框架控件
frame=gtk_frame_new("请注意下面的按钮排列");
gtk_container_add(GTK_CONTAINER(window),frame);//把frame添加到window内
//创建格装容器
table = gtk_table_new(4,4,FALSE);//创建4行4列,不允许均匀排放
gtk_container_set_border_width(GTK_CONTAINER(table),10);//设置格状容器的边线宽度为10
gtk_table_set_row_spacings(GTK_TABLE(table),5);//设定格状容器table中的控件行间隔5
gtk_table_set_col_spacings(GTK_TABLE(table),5);//设定格状容器table中的控件列间隔5
//把格状容器添加到frame内
gtk_container_add(GTK_CONTAINER(frame),table);
//gtk_table_attach,10个参数:格状容器,放入的控件,下面为table内的坐标比如1,3,1,3,就是横向1至3,和列向1至3
//后面四个为属性和间隔
//7,8参数为GtkAttachOptions,可取三个值:GTK_FILL可填充,GTK_EXPAND可扩展,GTK_SHRINK可缩放
//当然也可以使用gtk_table_attach_defaults函数只有4个参数,没有后面四个(属性和间隔)
button = gtk_button_new_with_label("0,1,0,1");
gtk_table_attach(GTK_TABLE(table),button,0,1,0,1,GTK_FILL,GTK_FILL,0,0);//0-1,0-1就是第一个格子
button = gtk_button_new_with_label("1,3,1,3");
gtk_table_attach(GTK_TABLE(table),button,1,3,1,3,GTK_FILL,GTK_FILL,0,0);//实际上是占了横向的第2和3的格子,纵向第2和3的格子
button = gtk_button_new_with_label("0,1,1,3");
gtk_table_attach(GTK_TABLE(table),button,0,1,1,3,GTK_FILL,GTK_FILL,0,0);//0-1,1-3
button = gtk_button_new_with_label("1,3,0,1");
gtk_table_attach_defaults(GTK_TABLE(table),button,1,3,0,1);//1-3,0-1
button = gtk_button_new_with_label("0,4,3,4");
gtk_table_attach_defaults(GTK_TABLE(table),button,0,4,3,4);//0-4,3-4
button = gtk_button_new_with_label("3,4,0,3");
gtk_table_attach_defaults(GTK_TABLE(table),button,3,4,0,3);//3-4,0-3
gtk_widget_show_all(window);
/***************************************************
gtk_widget_show(window)
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
button = gtk_button_new();
gtk_table_attach_defaults(GTK_TABLE(table),button,i,i+1,j,j+1);
gtk_widget_show(button);
}
********************************************************/
gtk_main();
return FALSE;
}//其Makefile文件为:
CC = gcc
all:
$(CC) table.c -o table `pkg-config gtk+-2.0 --cflags --libs`
运行后的结果为: