GTK提供了许多不同的容器组件,用户可以通过搭配不同的容器组件来控制子组件的布局方式。
容器组件如下:

  • GtkBox
  • GtkGrid
  • GtkRevealer
  • GtkStack
  • GtkOverlay
  • GtkPaned
  • GtkExpander
  • GtkFixed

1、GtkBox

GtkBox会将子组件以水平或垂直的方式布局。
image
在创建GtkBox容器传入的GtkOrientation参数将决定GtkBox是以水平还是垂直的方式组织子组件。
所有组件的大小都是一样的。
gtk_box_append:向GtkBox中添加子组件;
gtk_box_remove:从GtkBox中移除子组件;
gtk_box_insert_child_after:在特定位置添加子组件;
gtk_box_set_homogeneous:是否对GtkBox中的子组件强制分配相同的空间;
gtk_box_set_spacing:设置子组件之间的间隔距离;
gtk_box_reorder_child_after:移动子组件位置;

2、GtkGrid

GtkGrid容器将子组件以网格的方式进行组织。
image
在这个容器中可以随意指定子组件的具体位置和子组件占据的行数与列数。
gtk_grid_attach:向容器中添加子组件;
gtk_grid_attach_next_to:在已存在的子组件后一个位置放置组件;
gtk_grid_remove:从grid中移除子组件;

3、GtkRevealer

该容器用于将他的子组件由不可见转为可见。
如果想要自定义过渡动画,可以通过gtk_revealer_set_transition_type函数进行设置。
gtk_revealer_new:创建GtkRevealer对象。
该容器只能有一个子组件。
示例如下:

点击查看代码
#include <gtk/gtk.h>
#include "common_macro.h"

#define LABEL1 "button1"
#define WIN_TITLE "GtkRevealer Test"

LOCAL void clicked(GtkButton *btn, gpointer user_data)
{
    g_print("hide");
    gtk_revealer_set_reveal_child((GtkRevealer *)user_data, FALSE);
}

LOCAL void activate(GtkApplication *app, gpointer user_data)
{
    GtkWidget *win = gtk_application_window_new(app);
    GtkWidget *revealer = gtk_revealer_new();
    GtkWidget *btn = gtk_button_new_with_label(LABEL1);
    gtk_revealer_set_child((GtkRevealer *)revealer, btn);
    gtk_revealer_set_reveal_child((GtkRevealer *)revealer, TRUE);
    g_signal_connect(btn, SIGNAL_CLICKED, G_CALLBACK(clicked), revealer);

    gtk_window_set_title(GTK_WINDOW(win), WIN_TITLE);
    gtk_window_set_default_size(GTK_WINDOW(win), 200, 200);
    gtk_window_set_child(GTK_WINDOW(win), revealer);
    gtk_window_present(GTK_WINDOW(win));
}

int main(int argc, char **argv)
{
    GtkApplication *app = NULL;
    int status = 0;
    app = gtk_application_new(APP_ID, G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, SIGNAL_ACTIVATE, G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return status;
}

4、GtkStack

GtkStack和数据机构中的堆栈类似,同一时间只会显示顶层组件。
与GtkNotebook相比,GtkStack没有为用户提供更改可见子节点的方法。相反,GtkStackSwitcher或GtkStackSidebar等单独的小部件可以与GtkStack一起使用来提供此功能。
页面之间的切换动画可以通过gtk_stack_set_transition_type方法进行控制。
GtkStack为每个添加的子节点维护一个GtkStackPage对象,该对象保存每个子节点的额外属性。您可以使用gtk_stack_get_page()获得子节点的GtkStackPage,并且可以使用gtk_stack_get_pages()获得包含所有页面的GtkSelectionModel对象。
示例如下:

点击查看代码
#include <gtk/gtk.h>
#include "common_macro.h"

#define WIN_TITLE "GtkStack Test"

gboolean switch_btn = FALSE;

LOCAL void clicked(GtkButton *btn, gpointer user_data)
{
    g_print(gtk_button_get_label(btn));
    GtkSelectionModel *model = gtk_stack_get_pages(GTK_STACK(user_data));
    if (switch_btn) {
        gtk_selection_model_select_item(model, 0, TRUE);
        switch_btn = FALSE;
    } else {
        switch_btn = TRUE;
        gtk_selection_model_select_item(model, 1, TRUE);
    }
}

LOCAL void activate(GtkApplication *app, gpointer user_data)
{
    GtkWidget *win = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(win), WIN_TITLE);
    gtk_window_set_default_size(GTK_WINDOW(win), 200, 200);

    GtkWidget *stack = gtk_stack_new();
    GtkWidget *btn1 = gtk_button_new_with_label("button1");
    GtkWidget *btn2 = gtk_button_new_with_label("button2");
    GtkWidget *btn3 = gtk_button_new_with_label("button3");

    gtk_window_set_child(GTK_WINDOW(win), stack);
    gtk_stack_add_child(GTK_STACK(stack), btn1);
    gtk_stack_add_child(GTK_STACK(stack), btn2);

    g_signal_connect(btn1, SIGNAL_CLICKED, G_CALLBACK(clicked), stack);
    g_signal_connect(btn2, SIGNAL_CLICKED, G_CALLBACK(clicked), stack);

    gtk_window_present(GTK_WINDOW(win));
}

int main(int argc, char **argv)
{
    GtkApplication *app = NULL;
    int status = 0;
    app = gtk_application_new(APP_ID, G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, SIGNAL_ACTIVATE, G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return status;
}

5、GtkOverlay

GtkOverlay只能放置一个子组件,这个子组件的上面可以放置覆盖组件。
image
overlay组件的具体位置由GtkWidget:halignGtkWidget:valign属性指定。例如,当组件的垂直和水平对齐都被设置为GTK_ALIGN_START,那么这个组件就会被放置在GtkOverlay容器的左上角。
这个容器主要用于将一个组件放置在另一个组件之上。

点击查看代码
#include<gtk/gtk.h>
#include"common_macro.h"

LOCAL void activate(GtkApplication *app, gpointer user_data)
{
    GtkWidget *overlay = gtk_overlay_new();
    
    GtkWidget *btn1 = gtk_button_new_with_label("button1");
    gtk_overlay_set_child(GTK_OVERLAY(overlay), btn1);

    GtkWidget *win = gtk_application_window_new(app);
    gtk_window_set_default_size(GTK_WINDOW(win), 200, 200);
    gtk_window_set_title(GTK_WINDOW(win), "GtkOverlay Test");
    gtk_window_set_child(GTK_WINDOW(win), overlay);

    GtkWidget *btn2 = gtk_button_new_with_label("button2");
    gtk_widget_set_halign(btn2, GTK_ALIGN_START);
    gtk_overlay_add_overlay(GTK_OVERLAY(overlay), btn2);
    gtk_window_present(GTK_WINDOW(win));
}

int main(int argc, char **argv)
{
    GtkApplication *app = NULL;
    int status = 0;
    app = gtk_application_new(APP_ID, G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, SIGNAL_ACTIVATE, G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return status;
}

6、GtkPaned

GtkPaned组件拥有两个窗格,水平或者垂直。
image
用户可以通过拉动窗格分界线,调整两个窗格的比例。
通过gtk_paned_set_start_child和gtk_paned_set_end_child方法在两个窗格中添加子组件。这两个窗格之间的比例是子组件大小默认设置的,但是用户可以进行调整。
通常都是讲子组件放到GtkFrame中,然后再讲GtkFrame放到窗格中。如果只设置了一个窗格,那么将不会绘制分隔符。
每个子组件都有两个可以设置的选项,“resize”和“shrink”。如果设置为resize,那么当GtkPaned尺寸变化时,那么子组件的大小也会跟着变化。如果设置为“shrink”,那么子组件的大小会变得更小。
可以通过调用gtk_paned_set_position函数设置滑动条的位置。

点击查看代码
#include<gtk/gtk.h>
#include"common_macro.h"

LOCAL void activate(GtkApplication *app, gpointer user_data)
{
    GtkWidget *paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
    
    GtkWidget *btn1 = gtk_button_new_with_label("button1");

    GtkWidget *win = gtk_application_window_new(app);
    gtk_window_set_default_size(GTK_WINDOW(win), 200, 200);
    gtk_window_set_title(GTK_WINDOW(win), "GtkPaned Test");
    gtk_window_set_child(GTK_WINDOW(win), paned);

    GtkWidget *btn2 = gtk_button_new_with_label("button2");
    gtk_paned_set_start_child(GTK_PANED(paned), btn1);
    gtk_paned_set_end_child(GTK_PANED(paned), btn2);
    gtk_window_present(GTK_WINDOW(win));
}

int main(int argc, char **argv)
{
    GtkApplication *app = NULL;
    int status = 0;
    app = gtk_application_new(APP_ID, G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, SIGNAL_ACTIVATE, G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return status;
}

7、GtkExpander

GtkExpander可以让用户点击扩展三角形显示子元素。
image
如果想要在点击展开的时候进行自定义行为,可以使用notify::expanded信号。

点击查看代码
#include<gtk/gtk.h>
#include"common_macro.h"

LOCAL void activate(GtkApplication *app, gpointer user_data)
{
    GtkWidget *expander = gtk_expander_new("Test");
    GtkWidget *win = gtk_application_window_new(app);
    gtk_window_set_default_size(GTK_WINDOW(win), 200, 200);
    gtk_window_set_title(GTK_WINDOW(win), "GtkExpander Test");
    gtk_window_set_child(GTK_WINDOW(win), expander);
    GtkWidget *btn1 = gtk_button_new_with_label("btn1");
    gtk_expander_set_child(GTK_EXPANDER(expander), btn1);
    gtk_window_present(GTK_WINDOW(win));
    
}

int main(int argc, char **argv)
{
    GtkApplication *app = NULL;
    int status = 0;
    app = gtk_application_new(APP_ID, G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, SIGNAL_ACTIVATE, G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return status;
}
内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/servlet-context/p/17632691.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!