Clutter 布局管理

来源:互联网 发布:金十数据怎么看原油 编辑:程序博客网 时间:2024/06/05 09:31

 

引文

一般情况下各个 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(intargc,char*argv[])
{
        if(clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
                return1;
 
        /* 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 ();
          
        return0;
}

           

上述代码中,有关矩形与文本 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);

 Note:布局管理器(ClutterLayoutManager)的实例必须要与一个 Actor 容器(ClutterActor 的子类)实例相结合方可实现 Actor 的布局管理,上例中使用的 Actor 容器是        ClutterBox 容器。


           为了实现矩形与文本 Actor 在 Stage 上的居中放置,所以将 Box 容器的尺寸设置与 Stage 相同,然后使用 clutter_bin_layout_add() 向布局管理器中添加矩形与文本          Actor,并将它们在 Box 容器中的布局设为居中(CLUTTER_BIN_ALIGNMENT_CENTER)。

         最后将 Box 容器添加到 Stage 中,这样便可在 Stage 中显示文本框的效果,如下图所示。

        



三、流布局


如果要在 Stage 中将全部的 PDF 页面显示出来,那么建议使用流布局。因为只有流布局可以在一行(或一列)发生溢出时会自动进行换行(或换列)。看下面的示例:

#include <clutter/clutter.h>
#include <poppler/glib/poppler.h>
 
staticvoid
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(intargc,char*argv[])
{
        if(clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
                return1;
 
        /* 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 ();
          
        return0;
}

该示例只是对 [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 容器中。所得效果如下图所示:

   


Note:不过流布局在控制行高和列宽方面并非全自动的。对于水平流,只有行高可以自动调整;对于竖直流,只有列宽可以自动调整。因此 Box 容器中的 Actor 的宽、高依然需要程序员自行控制,否则很容易导致 Actor 变形。