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. xcode设置 - App内存暴增

    当你发现你的项目中什么没有写,只是启动App内存就飙升到50M甚至60M以上,那么请你接着往下看吧,本文对你绝对非常有用! 1. Enable zombie object: 为了方便我们调试程序,我们 ...

  2. 自己开发开源jquery插件--给jquery.treeview加上checkbox

    很多时候需要把树状的数据显示除来,比如分类,中国省份.城市信息,等,因此这方面的javascript插件也有很多.比如性能优异的jquery.treeview和国人开发的功能强大的zTree. 我最近 ...

  3. 实时数据处理环境搭建flume+kafka+storm:3.kafka安装

    1.  解压  tar -zxvf   2.配置/app/kafka_2.9.2-0.8.1.1/config/server.properties     #标识--     broker.id=0 ...

  4. Cookie Session Cache

    二. 工作机制 Ø Cookie :采用的是客户端保存信息的方案. Ø Session :采用服务器端保存信息的方案. Ø Cache :利用缓存 SRAM 来"静态"的保存写入信 ...

  5. PAT-乙级-1010. 一元多项式求导 (25)

    1010. 一元多项式求导 (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 设计函数求一元多项式的导数.(注:xn(n为整数)的一 ...

  6. 团体程序设计天梯赛-练习集L1-017. 到底有多二

    L1-017. 到底有多二 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一个整数“犯二的程度”定义为该数字中包含2的个数与其 ...

  7. uva 1421

    稍微有点新意的二分 #include<cstdio> #include<cstring> #include<algorithm> #include<cmath ...

  8. ural 1123

    找大于等于原数的最小回文数字  代码比较烂........... #include <iostream> #include <cstdio> #include <cstr ...

  9. Java的ResultSet中rs.next()含义

  10. Ubuntu 学习笔记

    1.   ubuntu开启root账号,设置分配很简单,只要为root设置一个root密码就行了: $ sudo passwd root 之后会提示要输入root用户的密码,连续输入root密码,再使 ...