众所周知,对于一个窗体来说,布局是非常重要的。就像Java Swing的各种layer,Gtk中也有各种布局。接下来我们就逐一说明
总览
在开始之前。本文的主要代码如下:
#include <libadwaita-1/adwaita.h>
static void activate_cb (GtkApplication *app) {
}
int main (int argc, char *argv[]) {
g_autoptr (AdwApplication) app = adw_application_new ("cn.hauchet.wangling", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate_cb), NULL);
return g_application_run (G_APPLICATION (app), argc, argv);
}
主要修改点在activate_cb
函数,故后文只展示该函数中的代码修改
GtkFixed
首先是GtkFixed
,这个就有点类似于绝对定位,需要我们手动定位每个控件。示例代码如下:
GtkWidget *window = gtk_application_window_new (app);
GtkWidget *button = gtk_button_new_with_label ("Button");
GtkWidget *label = gtk_label_new ("Hello World");
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *fixed = gtk_fixed_new();
gtk_fixed_put(GTK_FIXED(fixed), label, 50, 50);
gtk_fixed_put(GTK_FIXED(fixed), button, 50, 100);
gtk_window_set_child (GTK_WINDOW (window), fixed);
gtk_window_present (GTK_WINDOW (window));
在这里,我们将label放在(50,50)这个位置,button放在(50,100)这个位置。需要注意的是,GTK中使用布局需要新建一个GtkWidget
,例如这里就是
GtkWidget *fixed = gtk_fixed_new();
在GtkFixed
中使用gtk_fixed_put
参数将控件加入布局中。最后别忘了gtk_window_set_child (GTK_WINDOW (window), fixed);
将GtkFixed
加入到window中。
效果展示:
GtkBox
接下来是GtkBox
,也就是垂直或水平布局。使用这个布局前,我们同样需要新建一个GtkWidget
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
这里一共有两个参数,第一个参数指定了布局的方向,可选的值有GTK_ORIENTATION_HORIZONTAL
和GTK_ORIENTATION_VERTICAL
这两个分别表示了水平和垂直方向。第二个参数表示控件之间的间距。
在GtkBox
中想要添加控件,需要使用gtk_box_append
函数,添加顺序决定了控件显示顺序。
示例代码:
GtkWidget *window = gtk_application_window_new (app);
GtkWidget *button = gtk_button_new_with_label ("Button");
GtkWidget *label = gtk_label_new ("Hello World");
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_box_append (GTK_BOX (vbox), label);
gtk_box_append (GTK_BOX (vbox), button);
gtk_window_set_child (GTK_WINDOW (window), vbox);
gtk_window_present (GTK_WINDOW (window));
效果展示:
GtkTable
GtkTable
,顾名思义,是一个表格布局。在这个布局中使用下面这个语句来创建新的布局。
GtkWidget *table = gtk_grid_new();
在这个布局中,想要添加控件,需要使用到gtk_grid_attach
函数。
gtk_grid_attach(GTK_GRID(table), button1, 0, 0, 1, 1);
在这个示例代码中,有6个参数,分别是表格布局,需要添加的控件,列,行,列的跨度,行的跨度。
示例代码:
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *table = gtk_grid_new();
GtkWidget *button1 = gtk_button_new_with_label ("Button 1");
GtkWidget *button2 = gtk_button_new_with_label ("Button 2");
GtkWidget *button3 = gtk_button_new_with_label ("Button 3");
GtkWidget *button4 = gtk_button_new_with_label ("Button 4");
GtkWidget *button5 = gtk_button_new_with_label ("Button 5");
gtk_grid_attach(GTK_GRID(table), button1, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(table), button2, 1, 0, 1, 1);
gtk_grid_attach(GTK_GRID(table), button3, 0, 1, 1, 1);
gtk_grid_attach(GTK_GRID(table), button4, 1, 1, 1, 1);
gtk_grid_attach(GTK_GRID(table), button5, 0, 2, 2, 1);
gtk_window_set_child (GTK_WINDOW (window), table);
gtk_window_present (GTK_WINDOW (window));
效果展示:
GtkFlowBox
GtkFlowBox
是一种可以自动换行的布局。在这个布局中,使用以下语句新建布局:
GtkWidget *flowbox = gtk_flow_box_new();
想要添加控件,使用函数gtk_flow_box_insert
,例如:
gtk_flow_box_insert(GTK_FLOW_BOX(flowbox), button, -1);
一共有三个参数,第一个参数指定了flowbox,第二个参数指定了需要添加的控件,第三个参数是插入的位置,-1表示插入到最后。
示例代码:
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *flowbox = gtk_flow_box_new();
gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(flowbox), 3);
gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(flowbox), GTK_SELECTION_NONE);
for (int i = 1; i <= 10; i++) {
char button_label[20];
snprintf(button_label, sizeof(button_label), "Button %d", i);
GtkWidget *button = gtk_button_new_with_label(button_label);
gtk_flow_box_insert(GTK_FLOW_BOX(flowbox), button, -1);
}
gtk_window_set_child (GTK_WINDOW (window), flowbox);
gtk_window_present (GTK_WINDOW (window));
效果展示:
可以看到,控件位置跟随窗体大小发生了变化。
GtkStack
这个布局无论添加多少个控件,都只会显示一个,代码如下:
GtkWidget *stack = gtk_stack_new();
使用gtk_stack_add_titled
函数添加控件,参数有四个,分别指的是stack,控件,控件的name,控件的title
gtk_stack_add_titled(GTK_STACK(stack), button, button_label, button_label);
示例代码:
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *stack = gtk_stack_new();
gtk_stack_set_transition_type(GTK_STACK(stack), GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
gtk_stack_set_transition_duration(GTK_STACK(stack), 1000);
for (int i = 1; i <= 10; i++) {
char button_label[20];
snprintf(button_label, sizeof(button_label), "Button %d", i);
GtkWidget *button = gtk_button_new_with_label(button_label);
gtk_stack_add_titled(GTK_STACK(stack), button, button_label, button_label);
}
gtk_window_set_child (GTK_WINDOW (window), stack);
gtk_window_present (GTK_WINDOW (window));
效果展示:
GtkListBox
这个控件相当于一个列表,使用如下语句新建。
GtkWidget *listbox = gtk_list_box_new();
使用gtk_list_box_row_set_child
和gtk_list_box_append
添加控件,例如:
gtk_list_box_row_set_child(GTK_LIST_BOX_ROW(row), button);
gtk_list_box_append(GTK_LIST_BOX(listbox), row);
gtk_list_box_row_set_child
有两个参数,第一个参数指的是行,第二个参数指的是控件。gtk_list_box_append
也有两个参数,第一个参数指的是listbox,第二个参数指的是行。
示例代码:
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *listbox = gtk_list_box_new();
for (int i = 1; i <= 10; i++) {
char button_label[20];
snprintf(button_label, sizeof(button_label), "Button %d", i);
GtkWidget *button = gtk_button_new_with_label(button_label);
GtkWidget *row = gtk_list_box_row_new();
gtk_list_box_row_set_child(GTK_LIST_BOX_ROW(row), button);
gtk_list_box_append(GTK_LIST_BOX(listbox), row);
}
gtk_window_set_child (GTK_WINDOW (window), listbox);
gtk_window_present (GTK_WINDOW (window));
效果展示:
GtkPaned
这是一个从中间将左右或上下两边分开的布局,可以自由调节大小,新建布局的语句是:
GtkWidget *paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
这里有一个参数,分别可以是GTK_ORIENTATION_HORIZONTAL
和GTK_ORIENTATION_VERTICAL
。
这里我们同样新建两个GtkBox
用于存放按钮:
GtkWidget *box1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
GtkWidget *box2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
GtkPaned添加控件的语句是gtk_paned_set_start_child
。
示例代码:
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
GtkWidget *box1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
GtkWidget *box2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
for (int i = 1; i <= 5; i++) {
char button_label[20];
snprintf(button_label, sizeof(button_label), "Button %d", i);
GtkWidget *button = gtk_button_new_with_label(button_label);
gtk_box_append(GTK_BOX(box1), button);
}
for (int i = 6; i <= 10; i++) {
char button_label[20];
snprintf(button_label, sizeof(button_label), "Button %d", i);
GtkWidget *button = gtk_button_new_with_label(button_label);
gtk_box_append(GTK_BOX(box2), button);
}
gtk_paned_set_start_child(GTK_PANED(paned), box1);
gtk_paned_set_end_child(GTK_PANED(paned), box2);
gtk_window_set_child (GTK_WINDOW (window), paned);
gtk_window_present (GTK_WINDOW (window));
效果展示:
GtkScrolledWindow
使用这个布局的窗口,当内容超出窗口大小时,会自动出现滚动条。新建的语句为
GtkWidget *scrolled_window = gtk_scrolled_window_new();
这里同样混合使用GtkBox
,用于存放按钮。
添加控件使用gtk_scrolled_window_set_child
.
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolled_window), box);
示例代码:
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *scrolled_window = gtk_scrolled_window_new();
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
for (int i = 1; i <= 10; i++) {
char button_label[20];
snprintf(button_label, sizeof(button_label), "Button %d", i);
GtkWidget *button = gtk_button_new_with_label(button_label);
gtk_box_append(GTK_BOX(box), button);
}
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolled_window), box);
gtk_window_set_child(GTK_WINDOW(window), scrolled_window);
gtk_window_present(GTK_WINDOW(window));
效果展示:
那么这篇文章就写到这里,更多内容敬请期待。
评论