容器

:ref:`锚点<doc_size_and_anchors>`是处理图形用户界面中基本多分辨率处理的不同纵横比的有效方法,

对于更复杂的用户界面,它们可能会变得难以使用。

这通常是游戏的情况下,如角色扮演类、在线聊天、大富翁类或模拟类游戏。另一个需要更高级布局功能的常见情况是游戏内工具(或者仅仅是工具)。

这些情况需要一个更强大的类似操作系统的用户界面,具有先进的布局和格式。为此,:ref:`容器<class_container>`更有用。

Container layout

容器提供了巨大的布局能力(例如,Godot编辑器的用户界面就是完全使用它们完成的):

../../_images/godot_containers.png

当使用:ref:`容器<class_Container>`派生节点时,所有:ref:`控制<class_Control>`子节点放弃了自己的定位能力。这意味着*容器*将控制它们的位置,任何手动更改这些节点的尝试,都将在它们的父节点下一次调整大小时被忽略或失效。

Likewise, when a Container derived node is resized, all its children will be re-positioned according to it, with a behavior based on the type of container used:

../../_images/container_example.gif

例如*HBoxContainer*调整子按钮的大小。

容器的真正优势在于它们可以嵌套(作为节点),允许创建非常复杂的布局,调整毫不费力。

大小标志

当向容器添加节点时,容器对待每个子元素的方式,主要取决于它们的*尺寸标记*。通过检查*容器*的子控件,可以找到这些标记。

../../_images/container_size_flags.png

尺寸标记独立于垂直和水平尺寸,并不是所有容器都使用它们(但大多数容器都使用):

  • 填充:确保控件*填充*容器内指定的区域。无论控件是否*扩展*(见下面),当此选项被选中时(默认情况),只*填充*指定区域。
  • 扩展:尝试在父容器中使用尽可能多的空间(在每个轴中)。非扩展控件将被扩展控件推开。在扩展控件之间,相互占用的空间量由*比例*决定(见下文)。
  • **收缩中心**当扩展时(如果不填充),尽量保持在扩展区域的中心(默认情况下,它仍然位于左侧或顶部)。
  • **比例**扩展控件之间,相互占用可用空间的简单比例。一个比例为“2”的控件,将占用比例为“1”控件的两倍可用空间。

建议使用这些标记和不同的容器进行试验,以便更好地了解它们是如何工作的。

Container types

Godot提供了几种开箱即用的容器类型,因为它们有不同的用途:

Box Containers

垂直或水平排列子控件(通过:ref:水平盒子容器<class_HBoxContainer>`和:ref:`垂直盒子容器<class_VBoxContainer>)。在指定方向的相反方向(如水平容器的垂直方向),只是扩大了子节点的范围。

../../_images/containers_box.png

这些容器使用*比例*属性,用于设置*扩展*标记的子容器。

Grid Container

在网格布局中排列子控件(通过:ref:网格容器<class_GridContainer>,必须指定列的数量)。同时使用垂直和水平扩展标记。

../../_images/containers_grid.png

Margin Container

子控件被扩展到该控件的边界(通过:ref:边距容器<class_MarginContainer>)。根据主题配置,将在页边距上添加填充。

../../_images/containers_margin.png

同样,请记住边距是一个*主题*值,因此,如果需要单个控件,需要在常量覆盖部分编辑它们:

../../_images/containers_margin_constants.png

Tab Container

允许您将多个子控件堆叠在一起(通过:ref:选项卡容器<class_TabContainer>),只有*当前*可见。

../../_images/containers_tab.png

通过点击位于容器顶部的选项卡,来标记*当前*选项卡:

../../_images/containers_tab_click.gif

The titles are generated from the node names by default (although they can be overridden via TabContainer API).

在*选项卡容器*主题覆盖中,可以修改选项卡位置和*盒子样式*等内容。

Split Container

只接受一两个子控件,然后将它们与除数并排放置(通过:ref:水平分割容器<class_HSplitContainer>`和:ref:`垂直分割容器<class_VSplitContainer>)。同时考虑水平和垂直标记,以及*比例*。

../../_images/containers_split.png

可以拖动除数来改变两个子元素之间的大小关系:

../../_images/containers_split_drag.gif

PanelContainer

绘制*样式盒子*的简单容器,然后将子节点扩大到整个区域(通过:ref:面板容器<class_PanelContainer>,考虑*样式盒子*的边距)。它同时考虑水平和垂直尺寸标记。

../../_images/containers_panel.png

这个容器作为顶层非常有用,或者只是为布局各个部分添加自定义背景。

ScrollContainer

接受一个单独的子节点。如果这个节点比容器大,将添加滚动条以允许移动节点(通过:ref:滚动条容器<class_ScrollContainer>)。考虑垂直和水平尺寸标识,该行为可以在属性中的每个轴上打开或关闭。

../../_images/containers_scroll.png

鼠标滚轮和触摸拖动(当触摸可用时)也是平移子控件的有效方法。

../../_images/containers_center_pan.gif

在上面的例子中,使用此容器最常见的方法之一,是将*垂直盒子容器*作为子容器一起使用。

ViewportContainer

这是一个特殊的控件,它只接受单个*视口*节点作为子节点,它会像显示图像一样显示它(通过:ref:视口容器 <class_ViewportContainer>)。

Creating custom Containers

可以使用脚本轻松地创建自定义容器。下面是一个简单容器的例子,它适合于其矩形大小的子容器:

extends Container

func _notification(what):
    if (what==NOTIFICATION_SORT_CHILDREN):
        # Must re-sort the children
        for c in get_children():
            # Fit to own size
            fit_child_in_rect( c, Rect2( Vector2(), rect_size ) )

func set_some_setting():
    # Some setting changed, ask for children re-sort
    queue_sort()