Clutter 布局管理
[1] 中的各个 Actor 在 Stage 中的定位都是硬编码的方式实现的,当 Stage 的尺寸发生变化时,这些 Actor 的位置通常难以进行适应调整。Clutter 提供了布局管理机制,用来实现 Actor 的尺寸与位置控制。
Clutter (1.7.4)提供了五种布局方式:
- 固定布局(ClutterFixedLayout):跟 Actor 硬编码定位没有太多区别,通常不使用它;
- 单一布局(ClutterBinLayout):将 Actor 叠放成一摞,通常可用于将多个 Actor 复合在一起;
- 流布局(ClutterFlowLayout):当你不知道有多少个 Actor 的时候,并且又想让它们按照水平方向或竖直方向均匀排列,那么就可以使用流布局;
- 盒子布局(ClutterBoxLayout):将 Actor 单行水平或竖直均匀排列;
- 表格布局(ClutterTableLayout):将 Actor 按表格的方式均匀排列。
本文只介绍单一布局与流布局,其他布局方式与这两种布局大同小异。
单一布局
可以利用单一布局制作文本框。看下面的示例:
#include <clutter/clutter.h> int main(int argc, char *argv[]) { if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; /* Stage 的宽度与高度 */ gfloat w = 400, h = 200; ClutterColor stage_color = { 0x21, 0x43, 0x5e, 0xff }; ClutterColor rect_border_color = { 0xa0, 0x00, 0x00, 0xff }; ClutterColor text_color = { 0xff, 0xe6, 0xe6, 0xff }; /* 获取默认的 Stage 并设置其尺寸与颜色 */ ClutterActor *stage = clutter_stage_get_default (); clutter_stage_set_title (CLUTTER_STAGE (stage), "Hello Text Frame!"); clutter_actor_set_size (stage, w, h); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); /* 构建矩形 Actor */ ClutterActor *rectangle = clutter_rectangle_new_with_color (&stage_color); clutter_actor_set_size (rectangle, 0.5*w, 0.5*h); clutter_rectangle_set_border_width (CLUTTER_RECTANGLE (rectangle), 4); clutter_rectangle_set_border_color (CLUTTER_RECTANGLE (rectangle), &rect_border_color); /* 构建文本 Actor */ ClutterActor *text = clutter_text_new_with_text ("Sans 12", "中国人指望政府\n" "美国人指望 X 战警"); clutter_text_set_color (CLUTTER_TEXT (text), &text_color); clutter_text_set_line_alignment (CLUTTER_TEXT (text), PANGO_ALIGN_CENTER); /* 构建单一布局 */ ClutterLayoutManager *layout; layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, CLUTTER_BIN_ALIGNMENT_CENTER); /* 构建 Box 容器 */ ClutterActor *box = clutter_box_new (layout); clutter_actor_set_size (box, w, h); clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), rectangle, CLUTTER_BIN_ALIGNMENT_CENTER, CLUTTER_BIN_ALIGNMENT_CENTER); clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), text, CLUTTER_BIN_ALIGNMENT_CENTER, CLUTTER_BIN_ALIGNMENT_CENTER); /* 将 Box 容器添加至 Stage */ clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); /* 显示 Stage 及其子对象(矩形 Actor) */ clutter_actor_show_all (stage); /* 开启 Clutter 主循环,响应事件 */ clutter_main (); return 0; }
上述代码中,有关矩形与文本 Actor 的构建均在 [1] 中有所讲述。与布局相关的代码如下:
/* 构建单一布局 */ ClutterLayoutManager *layout; layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, CLUTTER_BIN_ALIGNMENT_CENTER); /* 构建 Box 容器 */ ClutterActor *box = clutter_box_new (layout); clutter_actor_set_size (box, w, h); clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), rectangle, CLUTTER_BIN_ALIGNMENT_CENTER, CLUTTER_BIN_ALIGNMENT_CENTER); clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), text, CLUTTER_BIN_ALIGNMENT_CENTER, CLUTTER_BIN_ALIGNMENT_CENTER); /* 将 Box 容器添加至 Stage */ clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);
布局管理器(ClutterLayoutManager)的实例必须要与一个 Actor 容器(ClutterActor 的子类)实例相结合方可实现 Actor 的布局管理,上例中使用的 Actor 容器是 ClutterBox 容器。
为了实现矩形与文本 Actor 在 Stage 上的居中放置,所以将 Box 容器的尺寸设置与 Stage 相同,然后使用 clutter_bin_layout_add() 向布局管理器中添加矩形与文本 Actor,并将它们在 Box 容器中的布局设为居中(CLUTTER_BIN_ALIGNMENT_CENTER)。
最后将 Box 容器添加到 Stage 中,这样便可在 Stage 中显示文本框的效果,如下图所示。
流布局
在 [2] 中谈到了在 Stage 中显示 PDF 页面的基本方法,但是实例中仅显示了三幅 PDF 页面。如果要在 Stage 中将全部的 PDF 页面显示出来,那么建议使用流布局。因为只有流布局可以在一行(或一列)发生溢出时会自动进行换行(或换列)。看下面的示例:
#include <clutter/clutter.h> #include <poppler/glib/poppler.h> static void pdf_page_actor_create (ClutterActor *box, PopplerDocument *doc, gint index) { gdouble w, h; PopplerPage *page = poppler_document_get_page (doc, index); poppler_page_get_size (page, &w, &h); ClutterActor *pdf_actor = clutter_cairo_texture_new (w, h); cairo_t *cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (pdf_actor)); cairo_rectangle (cr, 0, 0, w, h); cairo_set_source_rgb (cr, 1, 1, 1); cairo_fill (cr); poppler_page_render (page, cr); cairo_destroy (cr); clutter_actor_set_size (pdf_actor, 0.25*w, 0.25*h); clutter_box_pack (CLUTTER_BOX (box), pdf_actor, "x-align", CLUTTER_BOX_ALIGNMENT_CENTER, "y-align", CLUTTER_BOX_ALIGNMENT_CENTER, "expand", TRUE, NULL); } int main(int argc, char *argv[]) { if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; /* Stage 的宽度与高度 */ gfloat w = 640, h = 480; ClutterColor stage_color = { 0x21, 0x43, 0x5e, 0xff }; PopplerDocument *doc = poppler_document_new_from_file ("file:///your-pdf-file-path", NULL, NULL); /* 获取默认的 Stage 并设置其尺寸与颜色 */ ClutterActor *stage = clutter_stage_get_default (); clutter_stage_set_title (CLUTTER_STAGE (stage), "Hello Flow!"); clutter_actor_set_size (stage, w, h); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); /* 构建流布局 */ ClutterLayoutManager *layout = clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL); clutter_flow_layout_set_row_spacing (CLUTTER_FLOW_LAYOUT (layout), 8); clutter_flow_layout_set_column_spacing (CLUTTER_FLOW_LAYOUT (layout), 8); /* 构建 Box 容器 */ ClutterActor *box = clutter_box_new (layout); clutter_actor_set_size (box, w, h); gint total = poppler_document_get_n_pages (doc); for (gint i = 0; i < total; i++) pdf_page_actor_create (box, doc, i); /* 将 Box 容器添加至 Stage */ clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); /* 显示 Stage 及其子对象(矩形 Actor) */ clutter_actor_show_all (stage); /* 开启 Clutter 主循环,响应事件 */ clutter_main (); return 0; }
该示例只是对 [2] 的示例进行了少许修改,如下:
/* 构建流布局 */ ClutterLayoutManager *layout = clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL); clutter_flow_layout_set_row_spacing (CLUTTER_FLOW_LAYOUT (layout), 8); clutter_flow_layout_set_column_spacing (CLUTTER_FLOW_LAYOUT (layout), 8); /* 构建 Box 容器 */ ClutterActor *box = clutter_box_new (layout); clutter_actor_set_size (box, w, h); gint total = poppler_document_get_n_pages (doc); for (gint i = 0; i < total; i++) pdf_page_actor_create (box, doc, i);
首先构造了流布局管理器(水平方向流),并将它与 Box 容器结合,然后使用 poppler_document_get_n_pages() 获取 PDF 文档的页数,并使用我自定义的 pdf_page_create() 为每幅 PDF 页面建立一份 Cairo 纹理 Actor 并将其添加到 Box 容器中。所得效果如下图所示:
不过流布局在控制行高和列宽方面并非全自动的。对于水平流,只有行高可以自动调整;对于竖直流,只有列宽可以自动调整。因此 Box 容器中的 Actor 的宽、高依然需要程序员自行控制,否则很容易导致 Actor 变形。
参考文献
[1] 五个演员
转载时,希望不要链接文中图片,另外请保留本文原始出处:http://garfileo.is-programmer.com
2011年7月21日 16:28
木哈哈....
今天看了下clutter,发现已经把cogl独立出来了....
索性在mingw下编译了下1.7.4
附上链接
http://code.google.com/p/clutter-win32/downloads/list
回头有时间尝试下那个pinpoint能否在win下用....
2011年7月21日 17:02
@pingf: 嗯,而且 clutter 和 cogl 也快要到 2.0 了。看 wiki 上的信息,貌似 api 变动很多。