首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

如果要在窗口中放置多个控件,就要考虑如何编排控件的位置。GTK+提供了两种排列控件的方法:一是使用box(盒子),二是使用table(表格)。

12.5.1  使用box排列控件

1.创建和使用box容器

box是一种不可见的widget容器,它有水平排列和垂直排列两种。水平排列是控件按放入窗口的顺序水平排列,垂直排列是按控件放入窗口的顺序垂直排列。水平排列box容器使用函数gtk_hbox_new生成,而垂直排列box容器使用函数gtk_vbox_new生成。box容器生成后,使用函数gtk_box_pack_start或gtk_box_pack_end将控件放入容器中。前者由左向右、从上到下将控件放入box容器,而后者相反,由右至左,从下到上将控件放入box容器中。

下面是具体的函数定义:

Widget* gtk_hbox_new(gint homogeneous, gint spacing);

参数含义如下。

homogeneous:控制每个放入box的控件是否有同样的高或宽。

spacing:是否在控件之间填充空白。

void gtk_box_pack_start( GtkBox *box,

                              GtkWidget *child,

                              gint expand,

                              gint fill,

                              gint padding );

参数的含义如下。

l     box:要放入控件的box容器。

l     child:要放入box容器的控件。

l     expand:是否填满box所有额外控件,TRUE表示是,如果为FALSE则该box按控件原始大小显示。gtk_hbox_new函数的参数homogeneous值为TRUE时,该参数才有效。

l     fill:该值如果为TRUE,控件自行产生外控件;如果为FALSE,box在控件周围产生反白区域。只有expand为TRUE,该参数才有效。

这样的解释可能不好理解,来看一个例子程序就清楚了。在举例之前,先介绍一下按钮控件。

2.check按钮和radio按钮

生成一般的按钮有两个函数:gtk _button_new()和gtk _button_new_with_label()。前者产生一个无标签的按钮,后者生成一个有文本标签的按钮。

在开发中,也常常使用check按钮和radio按钮。它们都有两种状态,一个是选中,另外一个是未选中。所不同的是,在一组按钮中,radio按钮只能有一个被选中,其他都处于未选中状态,而check按钮没有这个限制。它们都是以双态按钮为基础的。可以使用以下函数生成一个双态按钮,第一个生成无标签按钮,第二个生成有文本标签的按钮。

GtkWidget* gtk_toggle_button_new(void);

GtkWidget* gtk_toggle_button_new_with_label(gchar *label);

对于双态按钮,经常需要在回调函数中判断按钮的状态是否被选中。方法如下:

void toggle_button_callback(GtkWidget *widget, gpointer data)

{

      if(GTK_TOGGLE_BUTTON(widget)->active)

      {

            //按钮被选择时的处理代码

      }

}

可以使用下面这个函数,设置按钮的状态:

void gtk_toggle_button_set_state(GtkToggleButton *toggle, gint state)

参数的含义如下。

l     toggle:要设置状态的按钮。

l     state:要设置的状态,值为TRUE把按钮设置为未选中状态,FLASE把按钮设置为选中。

生成check按钮的函数为:

GtkWidget* gtk_check_button_new(void);

GtkWidget* gtk_check _button_new_with_label(gchar *label);

生成radio按钮的函数为:

GtkWidget* gtk_radio_button_new(GSList *group);

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

radio按钮是成组出现的,因此需要一个参数group。

例12-3  按钮控件和box容器的使用,程序名为button_box.c。

#include<gtk/gtk.h>

/*按下某个按钮后,在命令行上打印出按钮名和新的状态*/

void click_button(GtkWidget *widget,gpointer *data)

{

      g_print("%s ",(char *)data);

      if(GTK_TOGGLE_BUTTON(widget)->active)

            g_print("state is active\n");

      else

            g_print("state is not active\n");

}

void destroy(GtkWidget *widget,gpointer *data)

{

      gtk_main_quit();

}

int main(int argc,char **argv)

{

      GtkWidget       *window;

      GtkWidget       *box;

      GSList          *group;

    GtkWidget       *check,*radio;

     

      gtk_init(&argc,&argv);

     

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      g_signal_connect(GTK_OBJECT(window),"destroy",

                         GTK_SIGNAL_FUNC(destroy),NULL);

      gtk_container_border_width(GTK_CONTAINER(window),50);

/*生成一个垂直box容器,并将该容器加入到主窗口中*/

      box = gtk_vbox_new(FALSE,0);

      gtk_container_add(GTK_CONTAINER(window),box);

     

      /*以下生成两个check按钮,将它们加入到box容器中,并显示出来*/

      check = gtk_check_button_new_with_label("coffee");

      g_signal_connect(GTK_OBJECT(check),"clicked",

                         GTK_SIGNAL_FUNC(click_button),"check button1");

      gtk_box_pack_start(GTK_BOX(box),check,TRUE,TRUE,0);

    gtk_widget_show(check);

     

      check = gtk_check_button_new_with_label("tea");

    g_signal_connect(GTK_OBJECT(check),"clicked",

                        GTK_SIGNAL_FUNC(click_button),"check button2");

    gtk_box_pack_start(GTK_BOX(box),check,TRUE,TRUE,0);

    gtk_widget_show(check);

     

      /*以下生成3个radio按钮,将它们加入到box容器中,并显示出来*/

      /*

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

*/

radio = gtk_radio_button_new_with_label(NULL,"Apple");

      g_signal_connect(GTK_OBJECT(radio),"clicked",

                          GTK_SIGNAL_FUNC(click_button),"Apple");

      gtk_box_pack_start(GTK_BOX(box),radio,TRUE,TRUE,0);

      gtk_widget_show(radio);

     

      group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));

      radio = gtk_radio_button_new_with_label(group,"Banana");

      g_signal_connect(GTK_OBJECT(radio),"clicked",

                          GTK_SIGNAL_FUNC(click_button),"Banana");

      gtk_box_pack_start(GTK_BOX(box),radio,TRUE,TRUE,0);

      gtk_widget_show(radio);

     

      group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));

      radio = gtk_radio_button_new_with_label(group,"Orange");

      g_signal_connect(GTK_OBJECT(radio),"clicked",

                    GTK_SIGNAL_FUNC(click_button),"Orange");

/*将第三个radio按钮设置为选中状态*/

      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio),TRUE);

      gtk_box_pack_start(GTK_BOX(box),radio,TRUE,TRUE,0);

      gtk_widget_show(radio);

     

      gtk_widget_show(box);

      gtk_widget_show(window);

     

      gtk_main();

      return 0;

}

运行程序后,显示如图12-3所示的界面。

图12-3  运行结果界面

12.5.2  使用table排列控件

1.创建和使用table容器

排列窗口中的控件的另一种方法是使用table(表格),可以把控件放到表格中指定的行和列中。

文本框:  
图12-4  表格行列编号方法

表格的行、列编号方法如图12-4所示。

例如,某个控件占据图12-4阴影部分,则它所占格子的坐标为left(左)0,right(右)2,top(上)1,bottom(下)3。

创建table(表格)容器的函数为:

GtkWidget* gtk_table_new( gint rows, gint columns, gint homogeneous );

参数的含义如下。

l     rows:表格所占的行数。

l     columns:表格所占的列数。

l     homogeneous:如果其值为TRUE,表格中每个格子的大小被定义为其中最大控件的大小;如果为FALSE,则格子的宽度与最宽控件的宽度相同,高度与放入表格的最高控件相同。

将控件放入表格中,可以使用函数:

void gtk_table_attach( GtkTable *table,

                          GtkWidget *child,

                          gint            left_attach,

                          gint            right_attach,

                          gint            top_attach,

                          gint            buttom_attach,

                          gint            xoptions,

                          gint            yoptions,

                          gint            xpadding,

                          gint            ypadding );

参数的含义如下。

l     table:要放入控件的表格。

l     child:要放入表格的控件。

l     left_attach、right_attach、top_attach、buttom_attach:控件在表格中的坐标。

l     xoptions、yoptions:指定了选项,可以是以下值或其组合:GTK_FILL,如果控件小于它所占用的格子,控件自动扩大到它所占格子的大小。GTK_SHRINK,如果控件大于它所占用的格子,控件自动缩小到它所占格子的大小。GTK_EXPAND,表格扩展,并利用窗口中所有可用的控件。

l     xpadding:指示控件与它所占格子左、右留出的空白大小,以像素表示。

l     ypadding:指示控件与它所占格子上、下留出的空白大小,以像素表示。

另一个将控件放入表格的函数是:

void gtk_table_attach_defaults( GtkTable      *table,

                                     GtkWidget      *child,

                                     gint            left_attach,

                                     gint            right_attach,

                                     gint            top_attach,

                                     gint            buttom_attach );

此函数参数的含义与gtk_table_attach()相同。

为了更准确地理解这些参数的含义,最好在运行例子程序时改变这些参数的值,然后查看程序显示的图形界面。

在演示表格控件的使用方法前,先介绍几个程序将会用到的控件。

2.标签控件

标签(label)控件在界面上显示一段文本。生成label控件的函数是:

GtkWidget* gtk_label_new(char *str);

生成标签控件后,修改所显示的文字可以使用下面的函数:

void gtk_label_set( GtkLabel *label, char *str );

获取当前标签所显示的文本的函数如下:

void gtk_label_get( GtkLabel *label, char **str );

3.编辑框控件

编辑框控件允许用户输入一行文本,生成编辑框的函数为:

GtkWidget* gtk_entry_new(void);

GtkWidget* gtk_entry_new_with_max_length(guint16 max);

其中,第二个函数限制了能输入到编辑框的最大字符数。

获取用户输入到编辑框架中的文本的函数是:

gchar* gtk_entry_get_text(GtkEntry *entry);

设置编辑框中的文本的函数是:

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

设置能输入到编辑框中的文本最大数的函数是:

void gtk_entry_set_max_length( GtkEntry *entry,guint16 max);

设置是否允许用户向编辑框中输入文本的函数是:

void gtk_entry_set_editable( GtkEntry *entry,gboolean editable);

例12-4  表格容器、box容器、标签控件和编辑框控件的使用,程序名为box.c。

#include<gtk/gtk.h>

/*函数声明*/

GtkWidget* makeTable();

GtkWidget* makeTextEntry();

GtkWidget* makecheckButtons();

GtkWidget* makeButtonBox();

/*单击check按钮的回调函数*/

void click_button(GtkWidget *widget,gpointer *data)

{

      g_print("click %s ",(char *)data);

      if(GTK_TOGGLE_BUTTON(widget)->active)

            g_print("and state is active\n");

      else

            g_print("and state is not active\n");

}

void destroy(GtkWidget *widget,gpointer *data)

{

      gtk_main_quit();

}

int main(int argc,char **argv)

{

      GtkWidget *window;

      GtkWidget *table;

      gtk_init(&argc,&argv);

     

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      g_signal_connect(GTK_OBJECT(window),"destroy",

                            GTK_SIGNAL_FUNC(destroy),NULL);

      gtk_container_border_width(GTK_CONTAINER(window),30);

      table = makeTable();

      gtk_container_add(GTK_CONTAINER(window),table);

      gtk_widget_show(window);

     

      gtk_main();

     

      return 0;

}

GtkWidget* makeTable()

{

      GtkWidget *table;

      GtkWidget *checkButtons;

      GtkWidget *textEntry;

      GtkWidget *buttonBox;

      /*创建table控件*/

      table = gtk_table_new(2,2,FALSE);

      gtk_widget_show(table);

    /*创建标签和编辑框*/

      textEntry = makeTextEntry();

      gtk_table_attach(GTK_TABLE(table),textEntry,

                      0,1,0,1,

                      GTK_FILL|GTK_EXPAND|GTK_SHRINK,0,

                      0,0);

      gtk_widget_show(textEntry);

      /*创建4个check按钮*/

      checkButtons = makecheckButtons();

      gtk_table_attach(GTK_TABLE(table),checkButtons,

                      1,2,0,1,

                        GTK_FILL | GTK_EXPAND,

                        GTK_FILL | GTK_EXPAND,

                        10,0);

      gtk_widget_show(checkButtons);

      /*创建两个按钮*/

      buttonBox = makeButtonBox();

      gtk_table_attach(GTK_TABLE(table),buttonBox,

                         0,2,1,2,

                      GTK_EXPAND|GTK_FILL|GTK_SHRINK,0,

                      5,10);

      gtk_widget_show(buttonBox);

      return table;

}

GtkWidget* makeTextEntry()

{

      GtkWidget *vbox;

      GtkWidget *label;

      GtkWidget *text;

      vbox = gtk_vbox_new(FALSE,5);

      /*生成标签控件*/

      label = gtk_label_new("please enter your name:");

      gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);

      gtk_widget_show(label);

      /*生成编辑框*/

      text = gtk_entry_new_with_max_length(15);

      gtk_box_pack_start(GTK_BOX(vbox),text,FALSE,FALSE,0);

      gtk_widget_show(text);

      return vbox;

}

GtkWidget* makecheckButtons()

{

      GtkWidget *vbox;

      GtkWidget *check;     

      vbox = gtk_vbox_new(FALSE,0);

      check = gtk_check_button_new_with_label("apple");

      g_signal_connect(GTK_OBJECT(check),"clicked",

                            GTK_SIGNAL_FUNC(click_button),"apple");

      gtk_box_pack_start(GTK_BOX(vbox),check,FALSE,FALSE,0);

      gtk_widget_show(check);

      check = gtk_check_button_new_with_label("banana");

      g_signal_connect(GTK_OBJECT(check),"clicked",

                            GTK_SIGNAL_FUNC(click_button),"banana");

      gtk_box_pack_start(GTK_BOX(vbox),check,FALSE,FALSE,0);

      gtk_widget_show(check);

      check = gtk_check_button_new_with_label("orange");

      g_signal_connect(GTK_OBJECT(check),"clicked",

                            GTK_SIGNAL_FUNC(click_button),"orange");

      gtk_box_pack_start(GTK_BOX(vbox),check,FALSE,FALSE,0);

      gtk_widget_show(check);

      check = gtk_check_button_new_with_label("pear");

      g_signal_connect(GTK_OBJECT(check),"clicked",

                            GTK_SIGNAL_FUNC(click_button),"pear");

      gtk_box_pack_start(GTK_BOX(vbox),check,FALSE,FALSE,0);

      gtk_widget_show(check);

      return vbox;

}

GtkWidget* makeButtonBox()

{

      GtkWidget *hbox;

      GtkWidget *button;

      hbox = gtk_hbox_new(FALSE,0);

      button = gtk_button_new_with_label("yes");

      gtk_box_pack_start(GTK_BOX(hbox),button,TRUE,TRUE,20);

      gtk_widget_show(button);

      button = gtk_button_new_with_label("no");

      gtk_box_pack_start(GTK_BOX(hbox),button,TRUE,TRUE,60);

      gtk_widget_show(button);

      return hbox;

}

程序运行后的界面如图12-5所示。

图12-5  运行结果界面

 

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论