从两个简单的函数开始
只有一个窗口
int main( int argc,
char *argv[] ) { GtkWidget *window;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_show (window);
gtk_main ();
return 0; } </source>
编译运行这个程序:
gcc -o base base.c `pkg-config gtk+-2.0 --cflags --libs` ./base
第一个gtk程序
带一个按钮的程序
实现那个”hello,world“:源代码
hello示例
编译运行这个hello.c:
gcc `pkg-config gtk+-2.0 --cflags --libs` -o hello hello.c ./hello
增加点东西
点击按钮时候,做点事情
这个hell2程序可以在点击hello按钮的时候弹出一个窗口:源代码

编辑hello2.c,并运行:
gcc `pkg-config gtk+-2.0 --cflags --libs` -o hello2 hello2.c ./hello2
多几个按钮
添加几个按钮:源代码
![]() |
| hello3示例 |
封装
使用box封装
gtk中的widget是封装在一起的,最常用的封装函数有:
gtk_hbox_new(等分空间与否,0); gtk_vbox_new(等分空间与否,0); gtk_box_pack_start(父控件,子控件,扩展与否,填充与否,0) gtk_box_pack_end(父控件,子控件,扩展与否,填充与否,0)
这有几个典型封装示例:
![]() |
| gtk_hbox_new示例1 |
void gtk_box_pack_start( GtkBox *box,
GtkWidget *child,
gboolean expand,
gboolean fill,
guint padding );
第一个参数和第二个参数都是一个Widget类型对象,把第二个控件封装到第一个控件里面。expand参数为TRUE时候,控件可以填充多余空间;为FALSE的时候,控件收缩到自身大小,不填充多余控件。这个值在gtk_hbox_new和gtk_vbox_new的一个值为TRUE的时候,就只有TRUE值,即此时FALSE不起作用。
fill的值只有expand值为TRUE有作用(如果gtk_hbox_new和gtk_vbox_new的第一个参数为TRUE,那么fill的值总是起作用)。FALSE表示控件不填充剩余空间,TRUE自动填充。
GtkWidget *gtk_hbox_new ( gboolean homogeneous,
gint spacing );
gtk_vbox_new和gtk_hbox_new相似,这里以gtk_hbox_new为例。homogeneous([.hɔməu'dʒi:njəs] adj. 同种的,同质的,均质的)指示box怎样对待包含在其中的控件。TRUE表示同等对待,视觉表示上就是每个控件占用的控件大小相等。FALSE为否。如果设置为TRUE,gtk_box_pack_start和gtk_box_pack_end函数都默认expand参数总是TURE。
下图是spacing和gtk_box_pack_start/end中的padding参数的效果:
![]() |
| gtk_hbox_new示例2 |
spacing是加载box中个控件对象之间的距离。padding是每个控件对象两边的距离。
使用table封装
GtkWidget *gtk_table_new( guint rows,
guint columns,
gboolean homogeneous );
第一个参数是行(rows),第二个参数是列(columns),第三个参数homogeneous指示table boxes是否自动调整大小。如果值为TRUE,表格中每个boxes都调整到最大的widget对象大小。FALSE表示使用收缩模式。行高是一行中的最高的widget的值,行宽是一列中最宽的widget的值。
一个rows=2,columns=2的table会是下面这个样子:
0 1 2 0+----------+----------+ | | | 1+----------+----------+ | | | 2+----------+----------+
上面的坐标系统(co-ordinate)从左上角开始(upper left hand corner)。要把一个widget放入box,使用下面函数:
void gtk_table_attach( GtkTable *table,
GtkWidget *child,
guint left_attach,
guint right_attach,
guint top_attach,
guint bottom_attach,
GtkAttachOptions xoptions,
GtkAttachOptions yoptions,
guint xpadding,
guint ypadding );
第一,第二个参数很明了。left_attach,right_attach是指widget要装入table的左右边界的y(纵)坐标,top_attach,bottom_attach指上下边界的x(横)坐标。都是gint(整形)值。上面是一个2x2的table,如果我们想把一个widget放到右下角的box中,可以设置:left_attach=1,right_attach=2,top_attach=1,bottom_attach=2。
table可以容许你把一个widget放到几个box(这box值table中的格子)中去。如果我们想把widget放到上表的最上一行两个表格中:left_attach=0,right_attach=2,top_attach=0,bottom_attach=1。
xoptions和yoptions指示封装选项,可以使用OR得到多个特性。它们的值可以有:
- GTK_FILL
如果table box比要放入的widget大,并且GTK_FILL设置了,那么widget会扩展到多余空间。
- GTK_SHRINK
如果table中的widget分配到了比它们自身需求更小的空间(比如用户调整窗口大小),widget通常显示不出来。如果GTK_SHRINK设置了,widget就会收缩调整大小。
- GTK_EXPAND
让table扩展到窗口中的多余空间。
padding参数和box封装中的意义相同。都是调整widget周边的空白空间。以pixels为单位的整数。
因为gtk_table_attach()有很多选项,所以gtk提供了一个带默认选项的函数:
void gtk_table_attach_defaults( GtkTable *table,
GtkWidget *widget,
guint left_attach,
guint right_attach,
guint top_attach,
guint bottom_attach );
defaults函数的X和Y选项设置为GTK_FILL|GTK_EXPAND,X和Y的padding值为0.其余参数意义和上面提到的相同。
同样还有gtk_table_set_row_spacing()和gtk_table_set_col_spacing(),它们设置table的行距和列距。对于列,spacing值为列右边的距离;对于行,spacing值为行下面的距离。注意,对于最后一行和列都不起作用。
void gtk_table_set_row_spacing( GtkTable *table,
guint row, // 哪一行
guint spacing );
void gtk_table_set_col_spacing ( GtkTable *table,
guint column, // 哪一列
guint spacing );
举例:创建一个2x2的table,放入3个widget,最后一个widget占用2个表格。源代码
![]() |
| GTK-TABLE学习示例 |
widget总结
Widget显示
在GTK中创建一个widget通常有几步:
- gtk_*_new()创建一个新的widget。
- gtk_window_new()
- gtk_vbox_new()
- gtk_hbox_new()
- gtk_table_new()
- gtk_button_new_with_label()
- 链接信号(signal)或事件(event)到我们的回调函数。
- 设置widget的属性
- 封装widget到container(通常译为包容器)
- gtk_container_add()
- gtk_box_pack_start()
- gtk_box_pack_end()
- gtk_table_attach_defaults()
- gtk_widget_show()显示widget
gtk_widget_show()显示已经设置好的widget,可以再次调用gtk_widget_hide()隐藏widget。显示的顺序不重要,都是通常都是显示好里面包含的widget再显示外面的widget。而且设置好一个widget就显示它,可以让这个变量再次使用。
Casting(类型检查宏)
gtk中有很多类型检查宏,可以在编译的时候防止我们出错:
G_OBJECT (object) GTK_WIDGET (widget) GTK_OBJECT (object) GTK_SIGNAL_FUNC (function) GTK_CONTAINER (container) GTK_WINDOW (window) GTK_BOX (box)
所有的GtkWidget都是从GObject基类派生出来的。所以可以使用G_OBJECT宏代替其他宏。
g_signal_connect( G_OBJECT (button), "clicked",
G_CALLBACK (callback_function), callback_data);
很多widget都可以作为container(包容器),所以很多widget都派生自GTK_CONTAINER类。在使用这样的widget处,使用这个类也是可以的。
widget继承
下面有一个类继承关系图,只有少数不赞成的类和附加类不在里面:
GObject | GtkObject +GtkWidget | +GtkMisc | | +GtkLabel | | | `GtkAccelLabel | | +GtkArrow | | `GtkImage | +GtkContainer | | +GtkBin | | | +GtkAlignment | | | +GtkFrame | | | | `GtkAspectFrame | | | +GtkButton | | | | +GtkToggleButton | | | | | `GtkCheckButton | | | | | `GtkRadioButton | | | | `GtkOptionMenu | | | +GtkItem | | | | +GtkMenuItem | | | | +GtkCheckMenuItem | | | | | `GtkRadioMenuItem | | | | +GtkImageMenuItem | | | | +GtkSeparatorMenuItem | | | | `GtkTearoffMenuItem | | | +GtkWindow | | | | +GtkDialog | | | | | +GtkColorSelectionDialog | | | | | +GtkFileSelection | | | | | +GtkFontSelectionDialog | | | | | +GtkInputDialog | | | | | `GtkMessageDialog | | | | `GtkPlug | | | +GtkEventBox | | | +GtkHandleBox | | | +GtkScrolledWindow | | | `GtkViewport | | +GtkBox | | | +GtkButtonBox | | | | +GtkHButtonBox | | | | `GtkVButtonBox | | | +GtkVBox | | | | +GtkColorSelection | | | | +GtkFontSelection | | | | `GtkGammaCurve | | | `GtkHBox | | | +GtkCombo | | | `GtkStatusbar | | +GtkFixed | | +GtkPaned | | | +GtkHPaned | | | `GtkVPaned | | +GtkLayout | | +GtkMenuShell | | | +GtkMenuBar | | | `GtkMenu | | +GtkNotebook | | +GtkSocket | | +GtkTable | | +GtkTextView | | +GtkToolbar | | `GtkTreeView | +GtkCalendar | +GtkDrawingArea | | `GtkCurve | +GtkEditable | | +GtkEntry | | `GtkSpinButton | +GtkRuler | | +GtkHRuler | | `GtkVRuler | +GtkRange | | +GtkScale | | | +GtkHScale | | | `GtkVScale | | `GtkScrollbar | | +GtkHScrollbar | | `GtkVScrollbar | +GtkSeparator | | +GtkHSeparator | | `GtkVSeparator | +GtkInvisible | +GtkPreview | `GtkProgressBar +GtkAdjustment +GtkCellRenderer | +GtkCellRendererPixbuf | +GtkCellRendererText | +GtkCellRendererToggle +GtkItemFactory +GtkTooltips `GtkTreeViewColumn
没有窗口的widget
有一些widget没有窗口,如果需要处理它们的信号事件,需要是用EventBox。
GtkAlignment GtkArrow GtkBin GtkBox GtkButton GtkCheckButton GtkFixed GtkImage GtkLabel GtkMenuItem GtkNotebook GtkPaned GtkRadioButton GtkRange GtkScrolledWindow GtkSeparator GtkTable GtkToolbar GtkAspectFrame GtkFrame GtkVBox GtkHBox GtkVSeparator GtkHSeparator
按钮控件(button widget)
普通按钮(normal buttons)
按钮按键通常有下面几个函数:
gtk_button_new_with_label("标签按钮") //创建带标签的按钮
gtk_button_new_with_mnemonic("_Press") //创建带提示符和其下划线的按钮,
提示符有快捷键功能。
gtk_button_new_from_stock() 创建包含图片和文字的按钮
gtk_button_new() 创建一个空白按钮,可以把一个封装其他widget的box发到里面
mnemonic [ni(:)'mɔnik(əl)]助记的,记忆的
在table例子基础上修改一下,把最后一个quit按钮改成一格大小,再增加一个button到最后一格里面。这个button包含一个box,box包含一个xpm图片和一个label。源代码 示例中使用的xpm图片
![]() |
| 带图片的按钮示例 |
按钮widget可以有下面这些信号:
pressed 按下 released 释放 clicked 点击 enter 鼠标移到按钮上 leave 鼠标移出按钮
开关按钮(toggle buttons)
开关按钮从普通按钮派生而来(derived from normal buttons),不过开关按钮只有两种状态,可以通过鼠标点击交换地改变状态。
创建开关按钮:
GtkWidget *gtk_toggle_button_new (void); GtkWidget *gtk_toggle_button_new_with_label (const gchar *label); GtkWidget *gtk_toggle_button_new_with_mnemonic ( const gchar *label);







