GTK+布局管理


GTK+ 布局管理

在本章中,我们将讲述如何将构件布置在窗口与对话框中。

当我们在设计应用程序的图形界面时,我们首先要决定的是在程序中用到哪种构件和管理应用程序中的这些构件。为了方便管理我们的构件,在GTK+通常使用不可见的构件称作layout containers. 。在本章节中,我们将设计其中的—— GtkAlignmentGtkFixedGtkVBox 和 GtkTable.

GtkFixed

容器构件GtkFixed 用于布置子构件在一个固定的位置和设定固定的大小。这种构件并不是属于自动的布局关系器。实质上,在我们设计的大多数应用程序中,我并不使用GtkFixed;而在只用于一些比较特殊的场合。例如,游戏,含有绘图功能的专用软件,那些需要移动和调整大小的软件(正如电子表格中的图表)以及那些小型的教育用途软件。

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *fixed; GtkWidget *button1;
GtkWidget *button2;
GtkWidget *button3; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "GtkFixed");
gtk_window_set_default_size(GTK_WINDOW(window), 290, 200);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), fixed); button1 = gtk_button_new_with_label("Button");
gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
gtk_widget_set_size_request(button1, 80, 35); button2 = gtk_button_new_with_label("Button");
gtk_fixed_put(GTK_FIXED(fixed), button2, 15, 15);
gtk_widget_set_size_request(button2, 80, 35); button3 = gtk_button_new_with_label("Button");
gtk_fixed_put(GTK_FIXED(fixed), button3, 100, 100);
gtk_widget_set_size_request(button3, 80, 35); g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0;
}

在我上面的这个例子中,我用代码生成了三个按钮构件然后把他们布局在固定的坐标上。当我们如果试图去改变窗口的大小的时候,其中按钮将会保持他们的大小和之前的坐标。

fixed = gtk_fixed_new();

上面的代码就可以生成了一个GtkFixed 的容器构件。

gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);

第一个按钮就 gtk_fixed_put()函数来进行布局,坐标为x=150, y=50.

Figure: GtkFixed container

GtkVBox

GtkVBox 是一种用于垂直布局的容器型构件。他把放置在他中的子构件放置在一个单独的列中。类似的是 GtkHBox也有相似的功能,有区别的在于他是用于水平布局,他的子构件是布置在一个单独的行中的。

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{ GtkWidget *window;
GtkWidget *vbox; GtkWidget *settings;
GtkWidget *accounts;
GtkWidget *loans;
GtkWidget *cash;
GtkWidget *debts; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 230, 250);
gtk_window_set_title(GTK_WINDOW(window), "GtkVBox");
gtk_container_set_border_width(GTK_CONTAINER(window), 5); vbox = gtk_vbox_new(TRUE, 1);
gtk_container_add(GTK_CONTAINER(window), vbox); settings = gtk_button_new_with_label("Settings");
accounts = gtk_button_new_with_label("Accounts");
loans = gtk_button_new_with_label("Loans");
cash = gtk_button_new_with_label("Cash");
debts = gtk_button_new_with_label("Debts"); gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), accounts, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), loans, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), cash, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), debts, TRUE, TRUE, 0); g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show_all(window); gtk_main(); return 0;
}

上面的这个按钮就显示了 GtkVBox的作用。他把五个按钮都布局在同一列上。如果你改变程序窗口的大小,其中的子构件(如按钮button)也会改变大小。

vbox = gtk_vbox_new(TRUE, 1);

上面程序中生成了GtkVBox。 我们把其中的第一个参数设置为 TRUE。这就意味着,程序中我的按钮都为同样的大小。至于按钮之间的距离大小被设置为“1”象素。

gtk_box_pack_start(GTK_BOX(vbox), settings, TRUE, TRUE, 0);

在上面的程序中我们把“settings “按钮布局在vbox容器构件中。 至于函数实参中的前两个参数,分别是容器构件和我们要放置的子构件。接下来的三个参数中分别是expand, fill和padding。 值得注意的是如果fill对应的参数是FALSE,则按钮就不会充满整个vbox构件。比较类似的是,如果之前在gtk_vbox_new(TRUE, 1);已经设置按钮都是等宽高了,所以expand对应的参数,是完全没有效果的。(译者注:此处建议fill expand都设为TRUE,至于具体区别和含义可在编程时感受)

Figure: GtkVBox container

GtkTable

GtkTable布局构件即可以按照行也可以按照列来布局她的子构件。

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{ GtkWidget *window; GtkWidget *table;
GtkWidget *button; char *values[16] = { "7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"
}; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 250, 180);
gtk_window_set_title(GTK_WINDOW(window), "GtkTable"); gtk_container_set_border_width(GTK_CONTAINER(window), 5); table = gtk_table_new(4, 4, TRUE);
gtk_table_set_row_spacings(GTK_TABLE(table), 2);
gtk_table_set_col_spacings(GTK_TABLE(table), 2); int i = 0;
int j = 0;
int pos = 0; for( i=0; i < 4; i++) {
for( j=0; j < 4; j++) {
button = gtk_button_new_with_label(values[pos]);
gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
pos++;
}
} gtk_container_add(GTK_CONTAINER(window), table); g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show_all(window); gtk_main(); return 0;
}

在以上的例子中,我们将仿照计算器编写一系列按钮。

table = gtk_table_new(4, 4, TRUE);

上面我们生成了一个新的GtkTable 布局构件,并设置为4行与4列。

gtk_table_set_row_spacings(GTK_TABLE(table), 2);
gtk_table_set_col_spacings(GTK_TABLE(table), 2);

上面我们就设置了每行与每列的距离。

for( i=0; i < 4; i++) {
for( j=0; j < 4; j++) {
button = gtk_button_new_with_label(values[pos]);
gtk_table_attach_defaults(GTK_TABLE(table), button, j, j+1, i, i+1 );
pos++;
}
}

以上代码将生成16个按钮并把他们布局在GtkTable容器构件中。

Figure: GtkTable container

GtkAlignment

GtkAlignment 容器构件控制了她的子构件的对齐方式与大小。

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{ GtkWidget *window;
GtkWidget *ok;
GtkWidget *close; GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *halign;
GtkWidget *valign; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 350, 200);
gtk_window_set_title(GTK_WINDOW(window), "GtkAlignment");
gtk_container_set_border_width(GTK_CONTAINER(window), 10); vbox = gtk_vbox_new(FALSE, 5); valign = gtk_alignment_new(0, 1, 0, 0);
gtk_container_add(GTK_CONTAINER(vbox), valign);
gtk_container_add(GTK_CONTAINER(window), vbox); hbox = gtk_hbox_new(TRUE, 3); ok = gtk_button_new_with_label("OK");
gtk_widget_set_size_request(ok, 70, 30);
gtk_container_add(GTK_CONTAINER(hbox), ok);
close = gtk_button_new_with_label("Close");
gtk_container_add(GTK_CONTAINER(hbox), close); halign = gtk_alignment_new(1, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), hbox); gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0); g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show_all(window); gtk_main(); return 0;
}

在上面的例子中,我们把两个按钮布局在了一个窗口的右下角。为了实现这个效果,我们用一个水平盒子构件horizontal box 、一个竖直盒子构件vertical box 和两个对齐容器构件(alignment containers)。

valign = gtk_alignment_new(0, 1, 0, 0);

上面的代码中我们生成了一个对齐容器构件。

gtk_container_add(GTK_CONTAINER(vbox), valign);

然后我们把对齐容器构件布局在水平盒子中(vbox)。

hbox = gtk_hbox_new(TRUE, 3);

ok = gtk_button_new_with_label("OK");
gtk_widget_set_size_request(ok, 70, 30);
gtk_container_add(GTK_CONTAINER(hbox), ok);
close = gtk_button_new_with_label("Close");
gtk_container_add(GTK_CONTAINER(hbox), close);

上面代码中,我们生成了一个水平盒子( horizontal box) 然后把两个按钮布局在其中。

halign = gtk_alignment_new(1, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), hbox); gtk_box_pack_start(GTK_BOX(vbox), halign, FALSE, FALSE, 0);

上面的代码中将生成一个对齐容器构件然后把布局在她中的子构件布局在右边。我们把水平盒子( horizontal box)添加到对齐容器构件中,然后又把对齐容器构件添加到竖直盒子中(vertical box)。 最后,我要振臂高呼一下,:)对齐容器构件( alignment container )中只能放置一个子构件,这就是为什么我们要用到那么多盒子来帮助我们布局那两个按钮了。

Figure: GtkAlignment container

Windows

接下来我们将展示一个更加高级一点的例子。具体就是展示一个窗口,你可以在JDeveloper IDE(一种java的集成开发软件)中发现这个例子的身影。

Figure: Windows dialog in JDeveloper

The dialog shows all opened windows, or more precisely tabs in JDeveloper application.

#include <gtk/gtk.h>

int main( int argc, char *argv[])
{ GtkWidget *window;
GtkWidget *table; GtkWidget *title;
GtkWidget *activate;
GtkWidget *halign;
GtkWidget *halign2; GtkWidget *valign;
GtkWidget *close;
GtkWidget *wins; GtkWidget *help;
GtkWidget *ok; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request (window, 300, 250);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_window_set_title(GTK_WINDOW(window), "Windows"); gtk_container_set_border_width(GTK_CONTAINER(window), 15); table = gtk_table_new(8, 4, FALSE);
gtk_table_set_col_spacings(GTK_TABLE(table), 3); title = gtk_label_new("Windows");
halign = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), title);
gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1,
GTK_FILL, GTK_FILL, 0, 0); wins = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(wins), FALSE);
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(wins), FALSE);
gtk_table_attach(GTK_TABLE(table), wins, 0, 2, 1, 3,
GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1); activate = gtk_button_new_with_label("Activate");
gtk_widget_set_size_request(activate, 50, 30);
gtk_table_attach(GTK_TABLE(table), activate, 3, 4, 1, 2,
GTK_FILL, GTK_SHRINK, 1, 1); valign = gtk_alignment_new(0, 0, 0, 0);
close = gtk_button_new_with_label("Close"); gtk_widget_set_size_request(close, 70, 30);
gtk_container_add(GTK_CONTAINER(valign), close);
gtk_table_set_row_spacing(GTK_TABLE(table), 1, 3);
gtk_table_attach(GTK_TABLE(table), valign, 3, 4, 2, 3,
GTK_FILL, GTK_FILL | GTK_EXPAND, 1, 1); halign2 = gtk_alignment_new(0, 1, 0, 0);
help = gtk_button_new_with_label("Help");
gtk_container_add(GTK_CONTAINER(halign2), help);
gtk_widget_set_size_request(help, 70, 30);
gtk_table_set_row_spacing(GTK_TABLE(table), 3, 6);
gtk_table_attach(GTK_TABLE(table), halign2, 0, 1, 4, 5,
GTK_FILL, GTK_FILL, 0, 0); ok = gtk_button_new_with_label("OK");
gtk_widget_set_size_request(ok, 70, 30);
gtk_table_attach(GTK_TABLE(table), ok, 3, 4, 4, 5,
GTK_FILL, GTK_FILL, 0, 0); gtk_container_add(GTK_CONTAINER(window), table); g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show_all(window);
gtk_main(); return 0;
}

以上代码将生成一个简单的GTK+窗口。

table = gtk_table_new(8, 4, FALSE);

我们使用table表格容器构件来进行布局。

title = gtk_label_new("Windows");
halign = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), title);
gtk_table_attach(GTK_TABLE(table), halign, 0, 1, 0, 1,
GTK_FILL, GTK_FILL, 0, 0);

上面的代码生成了一个标签,设为居左。这个标签被布局在GtkTable构件容器的第一列。

wins = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(wins), FALSE);
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(wins), FALSE);
gtk_table_attach(GTK_TABLE(table), wins, 0, 2, 1, 3,
GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 1);

文本显示构件占据了两行和两列。我们把该文本编辑构件的属性设置为editable 和光标隐藏(hide the cursor)。

valign = gtk_alignment_new(0, 0, 0, 0);
close = gtk_button_new_with_label("Close"); gtk_widget_set_size_request(close, 70, 30);
gtk_container_add(GTK_CONTAINER(valign), close);
gtk_table_set_row_spacing(GTK_TABLE(table), 1, 3);
gtk_table_attach(GTK_TABLE(table), valign, 3, 4, 2, 3,
GTK_FILL, GTK_FILL | GTK_EXPAND, 1, 1);

我们把两个靠在一起的按钮布局在文本编辑构件的左边也就是第四行(我们是从0开始记数的),我们把这两个按钮布局在“对齐构件”(alignment widget)中,这样我们就可以把他俩布局在顶部了。

Figure: Windows

GTK+布局管理的更多相关文章

  1. Swing布局管理器介绍

    创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/128174 当选 ...

  2. java基础 布局管理器

    概念: 组建在容器(比如JFrame)中的位置和 大小 是由布局管理器来决定的.所有的容器都会使用一个布局管理器,通过它来自动进行组建的布局管理. 种类: java共提供了物种布局管理器:流式布局管理 ...

  3. Qt之布局管理--基本布局

    Qt提供的布局类以及他们之间的继承关系QLayout-----QGirdLayout | ---QBoxLayout----QHBoxLayout | --QVBoxLayout----------- ...

  4. JAVA GUI布局管理器

    边界布局管理器: a.布局方式:是把整个容器划分为五个部分.东西南北中,南北要贯通,中间最大 (不仅是中间的范围最大,权利也最大)当周边不存在的时候中间会占领周边,当中间不存在的时候周边不能占据中间 ...

  5. Java Swing 第03记 布局管理器

    几种Swing常用的布局管理器 BorderLaout 它将容器分为5个部分,即东.南.西.北.中,每一个区域可以容纳一个组件,使用的时候也是通过BorderLayout中5个方位常量来确定组件所在的 ...

  6. AWT布局管理器

    布局管理器 容器内可以存放各种组件,而组件的位置和大小是由容器内的布局管理器来决定的.在AWT中为我们提供了以下5种布局管理器: ①   FlowLayout 流式布局管理器 ②   BorderLa ...

  7. SWT布局管理器

    一.充满式布局管理器(FillLayout类) FillLayout类是最简单的布局类,它把组件摆放成一行或者一列,并强制组件大小一致.一般,组件的高度与最高的组件一致,宽度与最宽的组件相同.,它里面 ...

  8. Java——布局管理器

    在Swing中使用的所有布局管理器都可以实现LayoutManager接口,在Swing中主要使用的5种布局管理器:FlowLayout.BorderLayout.GridLayout.CardLay ...

  9. Qt之Dialog\widget\ mainwindow的区别和布局管理器 & 分裂器的区别

    1.Dialog\widget\ mainwindow的区别 注意mainwindow和widget的区别,mainwindow都工具栏和菜单栏 Dialog and mainwinodws 都是继承 ...

随机推荐

  1. HttpWebRequest

    同步请求=====================================================================================  byte[] da ...

  2. drag drop小游戏

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  3. python学习笔记1(语法)

    语法 从"Hello,world"开始看吧,我们学的很多语言都是从helloworld开始的. >>> 1 + 1 2 >>> print 'H ...

  4. 简单3d RPG游戏 之 003 怪物AI

    游戏中,怪物会自动的往玩家所在地点走去,那需要创建一个C#脚本EnemyAI,包含两个功能: 1. 怪物旋转自己对准玩家 2. 怪物向前移动,追逐玩家 public class EnemyAI : M ...

  5. VS2008的默认打开重置为VS2008

  6. 1197: [HNOI2006]花仙子的魔法 - BZOJ

    Description Input 包含两个整数,并用一个空格隔开,第一个整数表示实施魔法的次数m,第二个整数表示空间的维数n.其中,1≤m≤100,1≤n≤15. Output 仅包含一个整数,表示 ...

  7. uva 10056

    概率 Q += p*pow(1-p, i*n+k-1) i = 0,1,2,3...... #include <cstdio> #include <cmath> int mai ...

  8. 浏览器对象模型(BOM)

    BOM结构 用户浏览网页的时候,浏览器会自动创建一些对象,这些对象存放着浏览器窗口的属性和相关信息,也就是大家熟称的BOM.浏览器对象模型是一个层次化的对象集,我们可以通过window对象访问所有对象 ...

  9. POJ 3191 The Moronic Cowmpouter(进制转换)

    题目链接 题意 : 将一个10进制整数转化为-2进制的数. 思路 :如果你将-2进制下的123转化为十进制是1*(-2)^2+2*(-2)^1+3*(-2)^0.所以十进制转化为-2进制就是一个逆过程 ...

  10. MVC开发过程中的疑难杂症

    MVC使用客户端验证 <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type=& ...