• Linux下图形界面编程——GTK+元件、信号与回调函数


    GTK界面基本元件

    需要包含#include<gtk/gtk.h>


    窗口

    1.         新建窗口

    gtk_window_new()可以建立一个GTK+窗口,函数原型如下:

    GtkWidget * gtk_window_new (GtkWindowType type);

    返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。

    参数type是一个表示窗口状态的常量,可能取值有以下两种:

    •   GTK_WINDOW_TOPLEVEL:表示该窗口是一个正常的窗口,可以最小化。
    •   GTK_WINDOW_POPUP:表示该窗口是一个弹出式的窗口,不可以最小化。

    2.         设置窗口标题

    gtk_window_set_title()函数用于设置窗口标题,使用方法如下:

    void gtk_window_set_title(GtkWindow *window, gchar *title);

    参数window指定将要添加标题的窗口,title表示需要设置的标题。需要注意title指向的字符串必须是英文字符,若需要显示中文字符,则需要使用g_locale_to_utf8()函数进行批注。

    3.         设置窗口大小与位置

    窗口大小指的是窗口的宽度和高度,用gtk_widget_set_usize()函数设置一个窗口的初始化大小。窗口位置指的是窗口的左上顶点到屏幕左边和顶边的距离,可以用gtk_widget_set_uposition()函数来设置一个窗口的初始位置。这两个函数的原型为:

    void gtk_widget_set_usize(GtkWidget *widget, gint width, gint height);

    void gtk_widget_set_uposition(GtkWidget *widget, gint x, gint y);

    参数widget用于指定将要进行设置的窗口,width表示窗口的宽度,height表示窗口的高度;x表示窗口的左边距,即左上顶点的x坐标,y表示窗口的上边距,也是窗口的左上顶点的y坐标。

    显示窗口需要调用gtk_widget_show()函数。


    标签

    1.         新建标签

    gtk_label_new()可以建立一个标签,函数原型如下:

    GtkWidget * gtk_label_new (gchar *text);

    返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。

    参数text表示标签需要显示的内容

    2.         将标签添加到窗口

    GTK+窗口中,除了window窗口外,其他元件都必须放置在一个容器中。新建的标签并不能直接显示,需要放在一个窗口元件中。gtk_container_add()函数作用是把一个元件放置在另一个元件窗口(窗口)中,函数原型如下:

    void gtk_container_add (GtkContainer *container, GtkWidget *widget);

    参数container是一个父级容器指针,widget是需要放置的元件指针。

    3.         设置与获取标签文本

    在程序中,可以用gtk_label_get_text()函数获取一个标签的文本。使用gtk_label_set_text()函数来设置一个标签的文本。这两个函数的原型为:

    const char* gtk_label_get_text (GtkLabel *label);

    void gtk_label_set_text (GtkLabel *label, gchar *text);

    第一个函数返回:若成功则返回标签文本的字符串指针,失败则返回NULL。

    函数中参数label是一个指向标签的指针,text表示标签需要设置的文本。

    显示标签需要调用gtk_widget_show()函数


    按钮

    1.         新建按钮

    gtk_button_new_with_label()可以建立一个带标签的按钮,函数原型如下:

    GtkWidget * gtk_button_new_with_label (gchar *label);

    返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。

    参数label表示按钮需要显示的内容

    2.         设置与获取按钮的标签

    gtk_button_get_label()函数可以获取一个按钮的标签。gtk_button_set_label()函数可以设置一个按钮的标签。这两个函数的原型为:

    const gchar* gtk_button_get_label (GtkButton *button);

    void gtk_button_set_label (GtkButton *button, const gchar *label);

    第一个函数返回:若成功则返回按钮标签内容的字符串指针,失败则返回NULL。

    函数中参数button是一个指向按钮的指针,label表示按钮的标签内容。按钮的使用通常伴随着GTK+信号与事件的产生。

    显示按钮需要调用gtk_widget_show()函数

      


    文本框

    1.         新建文本框

    gtk_entry_new()可以建立一个文本框,函数原型如下:

    GtkWidget * gtk_entry_new (void);

    返回:若成功则返回GtkWidget类型的指针,失败则返回NULL。

    另一个建立文本框的函数为:

    GtkWidget * gtk_entry_new_with_max_length (gint max);

    返回同上,参数max用来表示这个文本框最多可以输入的字节数。

    2.         设置与获取文本框数据

    gtk_entry_get_text()函数gtk_entry_set_text()函数可以得到和设置文本框的数据。这两个函数的原型为:

    const gchar* gtk_entry_get_text (GtkEntry *entry);

    void gtk_entry_set_text (GtkEntry *entry, const gchar *text);

    第一个函数返回:若成功则返回按钮标签内容的字符串指针,失败则返回NULL。

    函数中参数entry是一个指向文本框的指针,text表示设置到文本框中的字符串文本。

    显示文本框需要调用gtk_widget_show()函数

    example: 保存为entry_example.c

     1 #include <gtk/gtk.h>
     2 #include <stdlib.h>
     3  
     4  
     5  GtkWidget *window;
     6  GtkWidget *table;
     7  GtkWidget *entry;
     8  GtkWidget *label;
     9  GtkWidget *button;
    10  char text[50];
    11 
    12 void on_clicked(GtkWidget *widget, gpointer data)
    13 {
    14   strcpy(text, gtk_entry_get_text (GTK_ENTRY(entry)));
    15   printf("您输入到字符串是:%s:\n",text);
    16 }
    17 
    18  int main(int argc, char* argv[])
    19  {
    20      gtk_init(&argc, &argv);
    21      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    22      //设置窗口标题
    23      gtk_window_set_title(GTK_WINDOW(window), g_locale_to_utf8("文本框的使用", -1, NULL, NULL, NULL));
    24      //定义3行2列的表格,单元格大小根据单元格元件大小自动调整
    25      table = gtk_table_new(3, 2, FALSE);
    26      label = gtk_label_new(g_locale_to_utf8("请在这里输入文本", -1, NULL, NULL, NULL));
    27      //新建有字数限制的文本框,最多输入50个字符
    28      entry = gtk_entry_new_with_max_length(50);
    29      //新建提交按钮
    30      button = gtk_button_new_with_label(g_locale_to_utf8("提交", -1, NULL, NULL, NULL));
    31      //将表格添加到窗口中
    32      gtk_container_add(GTK_CONTAINER(window), table);
    33      //将三个元件分别添加到表格相应的位置
    34      gtk_table_attach (GTK_TABLE(table), label, 0, 1, 0, 1, 
    35              (GtkAttachOptions)(0), (GtkAttachOptions)(0), 10, 10);
    36      gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 1, 2, 
    37          (GtkAttachOptions)(0), (GtkAttachOptions)(0), 10, 10);
    38      gtk_table_attach (GTK_TABLE(table), button, 1, 2, 2, 3, 
    39          (GtkAttachOptions)(0), (GtkAttachOptions)(0), 10, 10);
    40      g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_clicked), window);
    41      gtk_widget_show_all(window);
    42      gtk_main();    
    43      return 0;
    44  }

     使用gcc编译

    gcc -o entry_example entry_example.c `pkg-config --libs --cflags gtk+-2.0`

    ./entry_example

    运行结果为

    在文本框中输入"hello world!"并点击提交,会在shell中显示

     


    界面布局元件

    GTK+的容器都是二进制的,也就是说每个容器只能放置一个元件,如果想在一个窗口中放置多个元件,则需要使用表格、窗格等有多个单元格的容器。

    表格

    1.表格的建立

    在窗口中使用表格,需要调用gtk_table_new()函数新建一个表格,函数原型如下:

    GtkWidget *gtk_table_new(guint rows, guint columns, gboolean homogeneous);

    返回:若成功则返回一个GtkWidget类型的指针,失败则放回NULL

    参数rows表示表格的行数,columns表示表格列数,类型是无符号整型。行列标号从边开始算起,如下图所示

    例如,某个元件占据了上图蓝色阴影部分,则它所占格子的坐标为left0, right2, top2, butoom4

    参数homogeneous是一个布尔值,TRUE表示每个单元格大小相同,所有单元格高度和宽度和表格中最大的一个相同;FALSE表示单元格大小会根据元件大小自动调整。

    表格的作用只是将窗口划分成不同的区域,并不能显示出这个表格。


    函数gtk_table_attach()作用是将一个元件添加到表格中,并设置在表格的位置和填充的选项。函数原型如下:

    void gtk_table_attach(GtkTable *table, GtkWidget *child, guint left_attach, guint right_attach, guint top_attach, guint buttom_attach,

    GtkAttachOptions xoptions, GtkAttachOptions yoptions,

    guint xpadding, guint ypadding);

    参数含义和作用:

    • table:容器表格的指针。
    • child:需要添加的元件的指针。
    • left_attachright_attach:分别表示元件的左边是表格x方向的第几条边,右边是表格x方向的第几条边。
    • top_attach, buttom_attach:分别表示元件的上边是表格y方向的第几条边,下边是表格y方向的第几条边。
    • xoptionsyoptions:分别表示元件在表格中的水平方向、垂直方向的对齐方式,取值类型为GtkAttachOptions
    • xpaddingypadding:分别表示元件与边框水平方向、垂直方向的边距。


    表格可以嵌套表格。

    下面为程序演示例子,保存为con_nested_table.c

     1 #include<gtk/gtk.h>
     2 
     3 int main(int argc, char *argv[])
     4 {
     5     GtkWidget *window;
     6     GtkWidget *table1;
     7     GtkWidget *table2;
     8     GtkWidget *button1;
     9     GtkWidget *button2;
    10     GtkWidget *entry1;
    11     GtkWidget *entry2;
    12     GtkWidget *entry3;
    13     GtkWidget *entry4;
    14     GtkWidget *label1;
    15     GtkWidget *label2;
    16     GtkWidget *label3;
    17     GtkWidget *label4;
    18     GtkWidget *label5;
    19     
    20     gtk_init(&argc, &argv);
    21     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    22     gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("用户信息", -1, NULL, NULL, NULL));//设置窗口标题
    23     //建立表格
    24     table1 = gtk_table_new (4, 4, FALSE);
    25     table2 = gtk_table_new (1, 2, FALSE);
    26     //定义5个标签、2个按钮、4个文本框
    27     label1 = gtk_label_new (g_locale_to_utf8("我的信息", -1, NULL, NULL, NULL));
    28     label2 = gtk_label_new (g_locale_to_utf8("用户名", -1, NULL, NULL, NULL));
    29     label3 = gtk_label_new (g_locale_to_utf8("密码", -1, NULL, NULL, NULL));
    30     label4 = gtk_label_new (g_locale_to_utf8("电子邮件", -1, NULL, NULL, NULL));
    31     label5 = gtk_label_new (g_locale_to_utf8("详细地址", -1, NULL, NULL, NULL));
    32     button1 = gtk_button_new_with_label(g_locale_to_utf8("注册", -1, NULL, NULL, NULL));
    33     button2 = gtk_button_new_with_label(g_locale_to_utf8("登录", -1, NULL, NULL, NULL));
    34     entry1 = gtk_entry_new ();
    35     entry2 = gtk_entry_new ();
    36     entry3 = gtk_entry_new ();
    37     entry4 = gtk_entry_new ();
    38     //添加表格到窗口
    39     gtk_container_add(GTK_CONTAINER (window), table1);
    40     //将5个元件分别添加到表格中
    41     gtk_table_attach (GTK_TABLE(table1), label1, 0, 3, 0, 1,
    42                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    43     gtk_table_attach (GTK_TABLE(table1), table2, 3, 4, 0, 1,
    44                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 5);
    45     gtk_table_attach (GTK_TABLE(table1), label2, 0, 1, 1, 2,
    46                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    47     gtk_table_attach (GTK_TABLE(table1), entry1, 1, 2, 1, 2,
    48                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    49     gtk_table_attach (GTK_TABLE(table1), label3, 2, 3, 1, 2,
    50                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    51     gtk_table_attach (GTK_TABLE(table1), entry2, 3, 4, 1, 2,
    52                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    53     gtk_table_attach (GTK_TABLE(table1), label4, 0, 1, 2, 3,
    54                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    55     gtk_table_attach (GTK_TABLE(table1), entry3, 1, 4, 2, 3,
    56                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    57     gtk_table_attach (GTK_TABLE(table1), label5, 0, 1, 3, 4,
    58                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    59     gtk_table_attach (GTK_TABLE(table1), entry4, 1, 4, 3, 4,
    60                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    61     gtk_table_attach (GTK_TABLE(table2), button1, 0, 1, 0, 1,
    62                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 2, 5);
    63     gtk_table_attach (GTK_TABLE(table2), button2, 1, 2, 0, 1,
    64                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 2, 5);
    65     gtk_widget_show_all(window);
    66     gtk_main();
    67     return 0;      
    68                  
    69                  
    70     }

    使用GCC编译

    gcc -o con_nested_table con_nested_table.c `pkg-config --libs --cflags gtk+-2.0`

    ./con_nested_table

     运行结果为


    框(box)是一種不可見的widget容器。框分为纵向框和横向框。纵向框在垂直方向堆积元件,横向框沿水平方向堆积元件。

    1.框的建立
    使用gtk_vbox_new函数建立纵向框,使用gtk_hbox_new函数建立横向框。函數原型爲:

    GtkWidget *gtk_hbox_new(gboolean homogeneous,gint spacing);
    GtkWidget *gtk_vbox_new(gboolean homogeneous,gint spacing);

    参数:

    • homogeneous子构件是否具有同样的大小
    • spacing 子构件间的距离

    建立框後,需要調用gtk_container_add()函數將這個框添加到窗口中。

    2.框中添加元件

    可以使用gtk_box_pack_start函数或gtk_box_pack_end函数将构件放到组装盒中。前者從左到右、從上到下將元件放入框容器,而後者從右到左,從下到上將元件放入框容器。其原型爲:

    void gtk_box_pack_start(GtkBox *box, GtkWidget *child, gboolean expend, gboolean fill, guint padding);
    void gtk_box_pack_end(GtkBox *box, GtkWidget *child, gboolean expend, gboolean fill, guint padding);

     

    参数:

    • box:框的名称
    • child子构件的名称
    • expend构件周围是否还有可扩充的空间
    • fill构件是否需要充分利用构件周围空间
    • padding构件周围要保留多少个填充的像元

    下面是使用垂直框的程序例子,保存爲vbox_example.c

     1 #include<gtk/gtk.h>
     2     GtkWidget *window;
     3     GtkWidget *table;
     4     GtkWidget *vbox;
     5     GtkWidget *button;
     6     GtkWidget *label;
     7     GtkWidget *entry;
     8     char text[50];
     9     char text1[50];
    10     char a[50];
    11     int i = 0;
    12     
    13 //定义信号回调函数
    14 void on_clicked(GtkWidget *widget, gpointer data)
    15 {
    16     ++i;
    17     gcvt((float)i, 3, text);
    18     strcat(text, ":");
    19     //获取文本框内容,并将其复制到text字符串数组中
    20     strcpy(text1, gtk_entry_get_text(GTK_ENTRY(entry)));
    21     strcat(text, text1);
    22     strcat(a, "\n");
    23     strcat(a, text);
    24     gtk_label_set_text(GTK_LABEL(label), a);
    25 }
    26 
    27 int main(int argc, char *argv[])
    28 {
    29         
    30     gtk_init(&argc, &argv);
    31     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    32     gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("我也来评论", -1, NULL, NULL, NULL));//设置窗口标题
    33     //设置窗口边框
    34     gtk_container_border_width(GTK_CONTAINER(window), 5);
    35     vbox = gtk_vbox_new (FALSE, 10);
    36     //建立表格    
    37     table = gtk_table_new (2, 2, FALSE);
    38     //定义标签、按钮、文本框
    39     label = gtk_label_new (g_locale_to_utf8("评论内容", -1, NULL, NULL, NULL));
    40     
    41     button = gtk_button_new_with_label(g_locale_to_utf8("发表评论", -1, NULL, NULL, NULL));
    42     
    43     entry = gtk_entry_new ();
    44     //添加表格到窗口
    45     gtk_container_add(GTK_CONTAINER (window), vbox);
    46     gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, FALSE, 5);
    47     gtk_box_pack_start (GTK_BOX(vbox), table, TRUE, FALSE, 5);
    48     //将元件分别添加到表格中
    49     gtk_table_attach (GTK_TABLE(table), entry, 0, 2, 0, 1,
    50                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    51     gtk_table_attach (GTK_TABLE(table), button, 1, 2, 1, 2,
    52                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 0);
    53     g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_clicked), window);
    54     gtk_widget_show_all(window);
    55     gtk_main();
    56     return 0;                       
    57     }

    使用GCC编译

    gcc -o vbox_example vbox_example.c `pkg-config --libs --cflags gtk+-2.0`

    ./vbox_example

     运行结果为

     


    其他常用元件

    1進度條、微調按鈕、組合框

    1.1進度條

    創建進度條要使用GtkAdjustment元件。gtk_adjustment_new()函數用於創建GtkAdjustment元件,函數原型如下:

    GtkObject* gtk_adjustment_new (gdouble initial_value, gdouble lower_range, gdouble upper_range, 

                   gdouble step_increment, gdouble page_increment, gdouble page_size);


    初始化新的调节设置对象需要6个参数。下面列出参数列表。

    • initial_value:当初始化时,调节设置对象中存储的值。
    • lower_range:调节设置对象允许的最小值。
    • upper_range:调节设置对象允许的最大值。
    • step_increment:当鼠标左鍵按下時元件一次增加/減少的值。
    • page_increment: 当鼠标右鍵按下時元件一次增加/減少的值
    • page_size:页的大小。这个值对于GtkSpinButton没什么用处,因此它总是被设置成为和page_increment同样的值,或者0


    GTK+中创建进度条的函数调用有兩個,函數原型如下:

    GtkWidget *gtk_progress_bar_new(void);

    GtkWidget *gtk_progress_bar_new_with_adjustment(GtkAdjustment *adjustmen);


    gtk_progress_bar_set_bar_style()函数用于设置进度条的样式,函数原型如下:

    gtk_progress_bar_set_bar_style(GtkProgressBar *pbar, GtkProgressBarStyle style);

    参数pbar是一个指向进度条的指針,style表示进度条的样式,取值如下:

    • GTK_PROGRESS_CONTINUOUS:连续进度条
    • GTK_PROGRESS_DISCRETE:条块进度条


    gtk_progress_bar_set_orientation()函数用于设置进度条的方向,函数原型如下:

    gtk_progress_bar_set_orientation(GtkProgressBar *pbar, GtkProgressBarOrientation orentation);

    参数pbar是一个指向进度条的指針,orientation表示进度条的方向,取值如下:

    • GTK_PROGRESS_LEFT_TO_RIGHT:从左往右显示
    • GTK_PROGRESS_RIGHT_TO_LEFT:从右往左显示
    • GTK_PROGRESS_BOTTOM_TO_TOP:从下往上显示
    • GTK_PROGRESS_TOP_TO_BOTTOM:从上往下显示


    gtk_progress_bar_update()函数用于更新进度条的进度状态,函数原型如下:

    void gtk_progress_bar_update(GtkProgressBar *pbar, gfloat percentage);

    参数pbar是一个指向进度条的指針,percentage表示进度条进度状态



    1.2微调按钮

    gtk_spin_button_new()用于创建微调按钮,函数原型如下:

    GtkWidget *gtk_spin_button_new (GtkAdjustment *adjustment, gdouble climb_rate, guint digits);

    参数climb_rate 表示微调按钮每步增加或减少的量,digits表示包含 的小数位数。


    还可以使用相关的函数条用获取和设置微调按钮的值。

    gtk_spin_button_get_value_as_float() 用于获取微调按钮的值,而gtk_spin_button_set_value()用于设置微调按钮的值,函数原型如下:

    gtk_spin_button_get_value_as_float(GtkSpinButton *spin_button);

    gtk_spin_button_set_value(GtkSpinButton *spin_button, gfloat value);

     

    1.3组合框

    组合框是文本框和列表框的组合,也称下拉列表。创建组合框要使用GList元件,用于保存列表框中将要显示的字符串。g_list_append()函数用于向GList中添加字符串,函数原型如下:

    GList *g_list_append(GList *glist, char *string);

    参数glist是一个指向列表框的指针,string指向将要添加至列表框中的字符串。


    gtk_combo_new()函数用于创建一个组合框,函数原型如下:

    GtkWidget *gtk_combo_new(void);


    gtk_combo_set_popdown_strings()函数用于设置组合框中显示的字符串,函数原型如下:

    gtk_combo_set_popdown_strings( GtkCombo *combo, GList *strings);

    参数combo是一个指向组合框的指针,strings表示组合框中将要显示的字符串。


    下面给出一个进度条、微调按钮和组合框的示例程序。control_example.c

     1 #include<gtk/gtk.h>
     2 
     3 int main(int argc, char *argv[])
     4 {
     5     GtkWidget *window;
     6     GtkWidget *vbox;    
     7     GtkWidget *label1;
     8     GtkWidget *label2;
     9     GtkWidget *label3;
    10     GtkWidget *bar;
    11     GtkWidget *spinbutton;
    12     GtkObject *adjustment;
    13     GList *glist;
    14     GtkWidget *combo;
    15     
    16     gtk_init(&argc, &argv);
    17     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    18     gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("控制元件", -1, NULL, NULL, NULL));//设置窗口标题
    19     //设置窗口边框宽度30
    20     gtk_container_border_width(GTK_CONTAINER(window), 30);
    21     //创建垂直框
    22     vbox = gtk_vbox_new(FALSE, 0);
    23     gtk_container_add(GTK_CONTAINER(window), vbox);
    24     
    25     //新建标签1
    26     label1 = gtk_label_new (g_locale_to_utf8("进度条", -1, NULL, NULL, NULL));
    27     //将标签添加到垂直框
    28     gtk_box_pack_start(GTK_BOX(vbox), label1, TRUE, TRUE, 0);
    29     //创建进度条
    30     adjustment = gtk_adjustment_new(70.0, 0.0, 100.0, 1.0, 0.0, 0.0);
    31     bar = gtk_progress_bar_new_with_adjustment(GTK_ADJUSTMENT(adjustment));
    32     gtk_progress_bar_set_bar_style(GTK_PROGRESS_BAR(bar), GTK_PROGRESS_CONTINUOUS);
    33     gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(bar), GTK_PROGRESS_LEFT_TO_RIGHT);
    34     //将进度条添加到垂直框
    35     gtk_box_pack_start(GTK_BOX(vbox), bar, TRUE, TRUE, 15);
    36 
    37     //新建标签2
    38     label2 = gtk_label_new (g_locale_to_utf8("微调按钮", -1, NULL, NULL, NULL));
    39     //将标签添加到垂直框
    40     gtk_box_pack_start(GTK_BOX(vbox), label2, TRUE, TRUE, 0);
    41     //创建微调按钮
    42     adjustment = gtk_adjustment_new(80.0, 0.0, 100.0, 1.0, 0.0, 0.0);    
    43     spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1.0, 1);
    44     //将微调按钮添加到垂直框
    45     gtk_box_pack_start(GTK_BOX(vbox), spinbutton, TRUE, TRUE, 15);
    46     
    47     //新建标签3
    48     label3 = gtk_label_new (g_locale_to_utf8("下拉列表", -1, NULL, NULL, NULL));
    49     //将标签添加到垂直框
    50     gtk_box_pack_start(GTK_BOX(vbox), label3, TRUE, TRUE, 0);
    51     //创建组合框
    52     glist = NULL;
    53     glist = g_list_append(glist, "banana");
    54     glist = g_list_append(glist, "apple");
    55     glist = g_list_append(glist, "orange");
    56     glist = g_list_append(glist, "pear");
    57     glist = g_list_append(glist, "strawberry");
    58     combo = gtk_combo_new();
    59     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
    60     //将组合框添加到垂直框
    61     gtk_box_pack_start(GTK_BOX(vbox), combo, TRUE, TRUE, 15);
    62     gtk_widget_show_all(window);
    63     gtk_main();
    64     return 0;                   
    65                  
    66     }

    使用GCC编译

    gcc -o control_example control_example.c `pkg-config --libs --cflags gtk+-2.0`

    ./control_example

     运行结果为

    2单选按钮(radio)、复选按钮(check)


    创建单选按钮函数有两个,原型如下:

    GtkWidget *gtk_radio_button_new(GSList *group);

    GtkWidget *gtk_radio_button_new_with_label(GSlist *group, gchar *label);

     

    创建复选按钮函数也有两个,原型如下:

    GtkWidget *gtk_check_button_new(void);

    GtkWidget *gtk_check_button_new_with_label( gchar *label);

     

    第一个函数创建无标签按钮,第二个函数用于创建带有文本标签的按钮。


    下面给出一个程序例子, check_radio.c

    注意:生产第一个radio按钮时,group参数为NULL,而以后每次在该组创建一个radio按钮时都要使用gtk_radio_button_group函数获得新的group

    
    
     1 #include<gtk/gtk.h>
     2 
     3 int main(int argc, char *argv[])
     4 {
     5     GtkWidget *window;
     6     GtkWidget *table;
     7     GtkWidget *label1;
     8     GtkWidget *label2;
     9     GSList *group;
    10     GtkWidget *check;
    11     GtkWidget *radio;
    12         
    13     gtk_init(&argc, &argv);
    14     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    15     gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("单选、复选按钮", -1, NULL, NULL, NULL));//设置窗口标题
    16     //设置窗口边框宽度15
    17     gtk_container_border_width(GTK_CONTAINER(window), 15);
    18     //建立表格
    19     table = gtk_table_new (4, 4, FALSE);
    20     //定义标签
    21     label1 = gtk_label_new (g_locale_to_utf8("业余时间活动爱好", -1, NULL, NULL, NULL));
    22     label2 = gtk_label_new (g_locale_to_utf8("平时每天学习时间", -1, NULL, NULL, NULL));
    23     
    24     //添加表格到窗口
    25     gtk_container_add(GTK_CONTAINER (window), table);
    26     //将元件分别添加到表格中
    27     gtk_table_attach (GTK_TABLE(table), label1, 0, 2, 0, 1,
    28                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 0);
    29     
    30     gtk_table_attach (GTK_TABLE(table), label2, 0, 2, 2, 3,
    31                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 5);
    32     //生成四个check按钮,分别添加到表格中
    33     check = gtk_check_button_new_with_label(g_locale_to_utf8("篮球", -1, NULL, NULL, NULL));
    34     gtk_table_attach(GTK_TABLE(table), check, 0, 1, 1, 2,
    35                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10);
    36                  
    37     check = gtk_check_button_new_with_label(g_locale_to_utf8("足球", -1, NULL, NULL, NULL));
    38     gtk_table_attach(GTK_TABLE(table), check, 1, 2, 1, 2,
    39                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10); 
    40                              
    41     check = gtk_check_button_new_with_label(g_locale_to_utf8("爬山", -1, NULL, NULL, NULL));
    42     gtk_table_attach(GTK_TABLE(table), check, 2, 3, 1, 2,
    43                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10);
    44                  
    45     check = gtk_check_button_new_with_label(g_locale_to_utf8("郊游", -1, NULL, NULL, NULL));
    46     gtk_table_attach(GTK_TABLE(table), check, 3, 4, 1, 2,
    47                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 10);
    48     
    49     //生成四个radio按钮,分别添加到表格中,注意:生产第一个radio按钮时,group参数为NULL,
    50     //而以后每次在该组创建一个radio按钮时都要使用gtk_radio_button_group函数获得新的group值
    51     radio = gtk_radio_button_new_with_label(NULL, g_locale_to_utf8("3~4小时", -1, NULL, NULL, NULL));
    52     gtk_table_attach(GTK_TABLE(table), radio, 0, 1, 3, 4,
    53                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    54                  
    55     group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));             
    56     radio = gtk_radio_button_new_with_label(group, g_locale_to_utf8("4~5小时", -1, NULL, NULL, NULL)); 
    57     gtk_table_attach(GTK_TABLE(table), radio, 1, 2, 3, 4,
    58                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    59                  
    60     group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));               
    61     radio = gtk_radio_button_new_with_label(group, g_locale_to_utf8("5~6小时", -1, NULL, NULL, NULL));
    62     gtk_table_attach(GTK_TABLE(table), radio, 2, 3, 3, 4,
    63                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);
    64                  
    65     group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));  
    66     radio = gtk_radio_button_new_with_label(group, g_locale_to_utf8(">=6小时", -1, NULL, NULL, NULL));
    67     gtk_table_attach(GTK_TABLE(table), radio, 3, 4, 3, 4,
    68                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 5, 5);             
    69                              
    70     gtk_widget_show_all(window);
    71     gtk_main();
    72     return 0;      
    73                  
    74                  
    75     }

    使用GCC编译

    gcc -o check_radio check_radio.c `pkg-config --libs --cflags gtk+-2.0`

    ./check_radio

     运行结果为

     

    3下拉菜单


    创建菜单的函数有两个,函数原型如下:

    GtkWidget *gtk_menu_new();

    GtkWidget *gtk_menu_new_with_label(gchar *label);

    第一个函数创建无标签菜单,第二个函数用于创建带有文本标签的菜单。


    创建菜单项的函数类似于创建菜单,函数原型如下:

    GtkWidget *gtk_menu_item_new();

    GtkWidget *gtk_menu_item_new_with_label(gchar *label);


    插入菜单项的函数原型如下:

    void gtk_menu_append (GtkMenu *menu, GtkWidget *child);

    void gtk_menu_item_set_submenu (GtkMenuItem item, GtkMenu *menu);


    创建菜单条函数原型如下:

    GtkWidget *gtk_menu_bar_new(void);

    向菜单条中加入菜单

    void gtk_menu_bar_append (GtkMenuBar *bar, GtkWidget *child);


    创建菜单的步骤如下:

    • 使用gtk_menu_new()生成一个新菜单。
    • 使用gtk_menu_item_new() gtk_menu_item_new_with_label()生成一个新的菜单项,然后使用 gtk_menu_item_append()将每一个菜单项加入到菜单中,使用 gtk_menu_item_new ()gtk_menu_item_new_with_label()创建主菜单项。
    • 使用 gtk_menu_item_set_submenu ()将各个菜单加入到主菜单项中。
    • 使用gtk_menu_bar_new()创建菜单条,这一步仅需做一次。然后使用 gtk_menu_bar_append 把主菜单项加入到菜单条上。

     下面是程序例子,menu_example.c

     1 #include<gtk/gtk.h>
     2 
     3 int main(int argc, char *argv[])
     4 {
     5     GtkWidget *window;
     6     GtkWidget *menu;
     7     GtkWidget *menubar;
     8     GtkWidget *rootmenu;
     9     GtkWidget *menuitem;
    10         
    11     gtk_init(&argc, &argv);
    12     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    13     gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("下拉菜单", -1, NULL, NULL, NULL));//设置窗口标题
    14     gtk_widget_set_usize(window, 200, 40);
    15     //创建新菜单,然后创建3个菜单项,并把菜单项加入到菜单中
    16     
    17     menu = gtk_menu_new();
    18     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("新建", -1, NULL, NULL, NULL));
    19     gtk_menu_append(GTK_MENU(menu), menuitem);
    20     
    21     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("打开", -1, NULL, NULL, NULL));
    22     gtk_menu_append(GTK_MENU(menu), menuitem);
    23     
    24     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("关闭", -1, NULL, NULL, NULL));
    25     gtk_menu_append(GTK_MENU(menu), menuitem);
    26     
    27     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("保存", -1, NULL, NULL, NULL));
    28     gtk_menu_append(GTK_MENU(menu), menuitem);
    29     
    30     //创建一个主菜单
    31     rootmenu = gtk_menu_item_new_with_label(g_locale_to_utf8("文件", -1, NULL, NULL, NULL));
    32     //将菜单加入到主菜单中
    33     gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu), menu);
    34     
    35     //创建菜单条
    36     menubar = gtk_menu_bar_new();
    37     //将主菜单项加入到菜单条
    38     gtk_menu_bar_append(GTK_MENU_BAR(menubar), rootmenu);
    39     
    40     //下面创建第二组菜单
    41     menu = gtk_menu_new();
    42     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("复制", -1, NULL, NULL, NULL));
    43     gtk_menu_append(GTK_MENU(menu), menuitem);
    44     
    45     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("剪切", -1, NULL, NULL, NULL));
    46     gtk_menu_append(GTK_MENU(menu), menuitem);
    47     
    48     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("粘贴", -1, NULL, NULL, NULL));
    49     gtk_menu_append(GTK_MENU(menu), menuitem);
    50     
    51     menuitem = gtk_menu_item_new_with_label(g_locale_to_utf8("删除", -1, NULL, NULL, NULL));
    52     gtk_menu_append(GTK_MENU(menu), menuitem);
    53     
    54     rootmenu = gtk_menu_item_new_with_label(g_locale_to_utf8("编辑", -1, NULL, NULL, NULL));
    55     //将菜单加入到主菜单中
    56     gtk_menu_item_set_submenu(GTK_MENU_ITEM(rootmenu), menu);      
    57     
    58     gtk_menu_bar_append(GTK_MENU_BAR(menubar), rootmenu);
    59     //将菜单条加入到窗口中
    60     gtk_container_add(GTK_CONTAINER(window), menubar);
    61                              
    62     gtk_widget_show_all(window);
    63     gtk_main();
    64     return 0;      
    65                  
    66                  
    67     }

    使用GCC编译

    gcc -o menu_example menu_example.c `pkg-config --libs --cflags gtk+-2.0`

    ./menu_example

     运行结果为

     

     下拉菜单截图工具截不出来。。


    信号与回调函数

    图形用户界面的程序是事件驱动的程序。程序进入gtk_ain()函数后,等待事件的发生,一旦发生某个事件,相应的信号将产生。如果程序中定义了相应的消息处理函数(也称回调函数),系统将自动进行调用。


    1添加信号

    信号的作用是对某个元件添加一个用户交互的功能。函数g_signal_connect() 可以把一个信号处理函数(或称回调函数)添加到一个元件上,在元件和消息处理函数间建立关联,该函数原型如下:

    gulong g_signal_connect (GtkObject *object, ghar *name,

    Gcallback callback_func, gpointer func_data);

    参数object是一个元件的指针,指向将产生信号的元件;name表示消息或事件的类型,

    一个按钮所有的事件类型与含义如下:

    • activate:激活的时候发生
    • clicked:单击以后发生
    • enter:鼠标指针进入这个按钮以后发生
    • leave:鼠标指针离开这个按钮以后发生
    • pressed:鼠标按下以后发生
    • released:鼠标释放以后发生


    参数callback_func表示信号产生后将要执行的回调函数,func_data为传递给回调函数的数据,与callback_func函数的第二个参数相同

    g_signal_connect函数中,使用事件的不同名称来区分不同的事件(即第二个参数name)。


    2回调函数

    消息处理函数(回调函数)原型如下:

    void callback_func (GtkWidget *widget, gpointer func_data);

    参数widget指向要接收消息的元件,参数 func_data指向消息产生时传递给该函数的数据。

    程序例子 signal_example.c

     1 #include<gtk/gtk.h>
     2     
     3     GtkWidget *window;
     4     GtkWidget *table;
     5     GtkWidget *button;
     6     GtkWidget *label1;
     7     GtkWidget *label2;
     8     GtkWidget *label3;
     9     int i = 0;
    10     
    11 //定义信号回调函数
    12 void on_clicked(GtkWidget *widget, gpointer data)
    13 {
    14     char a[20];
    15     ++i;
    16     gcvt((float)i, 3, a);
    17     
    18     gtk_label_set_text(GTK_LABEL(label2), a);
    19 }
    20 
    21 int main(int argc, char *argv[])
    22 {
    23         
    24     gtk_init(&argc, &argv);
    25     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    26     gtk_window_set_title (GTK_WINDOW (window), g_locale_to_utf8("信号与事件", -1, NULL, NULL, NULL));//设置窗口标题
    27     //设置窗口边框
    28     gtk_container_border_width(GTK_CONTAINER(window), 5);
    29     
    30     //建立表格    
    31     table = gtk_table_new (2, 3, FALSE);
    32     //定义标签、按钮
    33     label1 = gtk_label_new (g_locale_to_utf8("点击按钮第", -1, NULL, NULL, NULL));
    34     label2 = gtk_label_new (g_locale_to_utf8("0", -1, NULL, NULL, NULL));
    35     label3 = gtk_label_new (g_locale_to_utf8("", -1, NULL, NULL, NULL));
    36     button = gtk_button_new_with_label(g_locale_to_utf8("计数", -1, NULL, NULL, NULL));
    37     
    38     
    39     //添加表格到窗口
    40     gtk_container_add(GTK_CONTAINER (window), table);
    41     
    42     //将元件分别添加到表格中
    43     gtk_table_attach (GTK_TABLE(table), label1, 0, 1, 0, 1,
    44                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10);
    45     gtk_table_attach (GTK_TABLE(table), label2, 1, 2, 0, 1,
    46                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10);
    47     gtk_table_attach (GTK_TABLE(table), label3, 2, 3, 0, 1,
    48                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10);
    49     gtk_table_attach (GTK_TABLE(table), button, 2, 3, 1, 2,
    50                  (GtkAttachOptions)(0), (GtkAttachOptions)(0), 0, 10);             
    51     g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(on_clicked), window);
    52     gtk_widget_show_all(window);
    53     gtk_main();
    54     return 0;                       
    55     }

    使用GCC编译

    gcc -o signal_example signal_example.c `pkg-config --libs --cflags gtk+-2.0`

    ./signal_example

     运行结果为

    The End!

    不经历风雨,怎么见彩虹!
  • 相关阅读:
    Blazor使用Chrome远程调试
    Blazor登录Ids4
    Jenkins + Coding 构建 Docker Image 并自动上传至Docker Registry
    EFK 数据生命周期
    EFK (Elasticsearch + Fluentd + Kibana) 日志分析系统
    通过Nginx代理Grafana,并通过域名访问
    Prometheus搜集mysql和nginx log指标
    java 线程相关(4)
    java 并发相关(5)
    java 线程相关(3)
  • 原文地址:https://www.cnblogs.com/ivorfeng/p/3096433.html
Copyright © 2020-2023  润新知