GTK--布局管理

版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/46432975

这一小结,将要学习将构建布局在窗口和对话框中.为了方便的管理我们的构件,在GTK+中,通常使用不可见的构件称作layout containers.
这一小节将要讨论GtkAlignment,GtkFixed,GtkVBox,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;
}

下面是运行的结果:

GTK--布局管理

在上面的例子中,我们使用代码生成了三个按钮,这三个按钮布局在固定的位置上.当窗口的大小改变的时候,按钮将会固定保持他们的大小和固定的坐标.

使用函数gtk_fixed_new()就能够生成一个GtkFixed的容器构件.如果我们想要想容器中添加组件,使用函数:
gtk_fixed_put(),例如gtk_fixed_put(GTK_FIXED(fixed),button1,150,50);

button1的坐标为x=150,y=50

(二):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;
}

下面是程序的运行结果:

GTK--布局管理

效果很明显,垂直排版,所以我们在排版菜单选项的时候,就是使用这个工具的.

在上面这个例子中,如果改变窗口大小的时候,按钮的大小也会发生改变的.
使用函数gtk_vbox_new()可以生成GtkBox构件.在本例子中:

vbox = gtk_vbox_new(TRUE,1);
第一个参数设置为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对应的参数是完全没有效果的.(在这里尽量这两个参数都设置成TRUE).

(三):GtkTable容器
GTkTabel容器,顾名思义,该容器类似于一个表格,既可以按照行来布局,也可以按照列来布局.

下面是我们的一个例子.

#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;
}

下面是运行之后的效果:

GTK--布局管理

通过上面运行的效果,我们看到我们做的是一个计算机的布局.

table = gtk_table_new(4,4,TRUE);

这样就生成了一个GtkTabel布局构件,并设置为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容器构件中.

(四):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;
}

下面是程序运行的结果:

GTK--布局管理

在这个例子中,将两个按钮布局到一个窗口的右下角.为了实现这个效果,我们使用了一个水平盒子构建horizontal box,一个竖直盒子构建vertical box和两个对齐容器构件alignment containers.

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

这样生成一个对齐容器构件.

gtk_conatiner_add(GTK_CONTAINER(vbox),valign);

将对齐容器构件布局在水平盒子中.

    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);

上述代码生成一个对齐容器构件,然后将其子控件布局在右边,我们把水平盒子添加到对齐容器构件中,然后又把对齐容器构件添加到竖直盒子中.

注意:对齐容器构建只能放置一个子构件.所以要用盒子构件来帮助布局.

(五)​:Windows

该构件是一个比较常用的构建,我们先看一下在代码中如何使用,再看一下运行之后的结果:

#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("Window");
    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_FILL,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--布局管理

在下面的一个小节当中,我们将要了解gtk+图形开发中至关重要的一个问题,就是通过signal来实现事件的监听,同时了解一下信号机制的内部原理。

上一篇:C#:在AnyCPU模式下使用CefSharp


下一篇:Skype 正式为 iOS 和 Android 用户推出移动端群组视频聊天功能