Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

使用容器

锚点是 GUI 中处理基本多分辨率时应对不同纵横比的有效方法。

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

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

这些情况需要一个更强大的类似操作系统的用户界面,具有先进的布局和格式。用 Container 会更方便。

容器布局

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

../../_images/godot_containers.png

当使用 Container 派生的节点时,所有作为子项的 Control 节点都会放弃自我定位能力。这意味着容器将控制它们的位置,任何手动更改这些节点的尝试,都将在它们的父节点下一次调整大小时被忽略或失效。

同样,调整 Container 派生节点的大小时,它的所有子节点都将根据它重新定位,其行为基于所用的容器类型:

../../_images/container_example.gif

HBoxContainer 节点调整子按钮大小的例子。

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

大小选项

当将节点添加到容器中时,容器如何处理每个子节点主要取决于它们的 容器尺寸选项(container sizing options)。这些选项可以通过检查任何作为 Container 子节点的 Control 的布局来查看。

../../_images/container_sizing_options.webp

尺寸选项在垂直和水平方向上是相互独立的,并非所有容器都会使用这些选项(但大多数都会使用):

  • 填充(Fill):确保控件能够填充满容器内的指定区域。无论控件是否 扩展(见下文),只有选中此选项时(默认情况),控件才会填充指定区域。

  • 扩展(Expand):尝试在父容器(的每个轴上)尽可能多地利用空间。未启用扩展的控件会被启用扩展的控件所挤开。在启用扩展的控件之间,它们彼此占用的空间量由拉伸比例(见下文)决定。此选项仅在父容器的类型符合要求时可用,例如 HBoxContainer 节点就具有此选项用于水平尺寸调整。

  • 起始收缩(Shrink Begin):当启用扩展时,尝试保持在扩展区域的左侧或顶部。

  • 收缩居中(Shrink Center):当启用扩展时,尝试保持在扩展区域的中心。

  • 收缩结束(Shrink End):当启用扩展时,尝试保持在扩展区域的右侧或底部。

  • 拉伸比例(Stretch Ratio):决定扩展控件之间如何分配可用空间的比率。比率为“2”的控件获得的可用空间是比率为“1”的控件的两倍。

建议多加尝试这些标志和不同的容器,以便更好地理解它们的工作方式。

容器类型

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

盒式容器

它们会把子控件按照垂直或水平方向进行排列(分别通过 HBoxContainerVBoxContainer 来实现)。而在与排列方向垂直的另一个方向上(比如水平容器的垂直方向),它会直接把子控件拉伸铺满。

../../_images/containers_box.png

这些容器会利用 Stretch Ratio(拉伸比例) 属性,来给那些开启了 Expand(展开) 标志的子控件分配空间。

网格容器

将子控件按照网格排列(使用 GridContainer ,必须指定列数),会同时用到垂直和水平扩展选项。

../../_images/containers_grid.png

边距容器

将子节点扩展到该控件的边界(使用 MarginContainer ),会根据主题的设置来添加不同大小的边距。

../../_images/containers_margin.png

同样, 请记住, 边距是一个 Theme 值, 所以它们需要从每个控件的常量重写部分进行编辑:

../../_images/containers_margin_constants.png

选项卡容器

允许你将多个子控件堆叠在一起(使用 TabContainer ),只会显示 当前 控件。

../../_images/containers_tab.png

点击容器顶部的选项卡可以更改 当前 控件:

../../_images/containers_tab_click.gif

标题默认是根据节点名称生成的(尽管可以通过 TabContainer 的 API 重写)。

可以在 TabContainer 的主题覆盖项中修改类似选项卡位置和 StyleBox 等设置。

拆分容器

将子控件垂直或水平排列,并在它们之间创建可拖动的分割条(通过 HSplitContainerVSplitContainer 实现)。它同时支持水平和垂直方向的扩展(expand)标志,以及 拉伸比例(Stretch Ratio)。

../../_images/containers_split.png

可以通过拖动分割条(grabbers)来改变子控件之间的大小比例。

../../_images/containers_split_drag.gif

PanelContainer

这种容器会先绘制一个 StyleBox (样式盒,比如背景图或边框),然后自动把里面的子控件拉伸放大,让它们铺满整个区域(具体参考 PanelContainer )。在铺满的时候,它还会非常懂事地避开 StyleBox 自带的边距(margins)。同时,它也支持水平和垂直方向的尺寸设置选项。

../../_images/containers_panel.png

这种容器非常适合拿来当整个界面的顶级(最外层)控件,或者用来给布局里的某个区域单独加个自定义的背景样式。

可折叠容器

这是一种可以通过交互来展开或折叠(收起)的容器(具体参考 FoldableContainer )。当它处于折叠状态时,里面的子控件就会被自动隐藏起来。

ScrollContainer

它只能接收一个子节点。如果这个子节点的尺寸比容器本身还要大,容器就会自动弹出滚动条,让你可以通过拖拽或滑动来查看节点的其他部分(具体参考 ScrollContainer )。它同时支持水平和垂直方向的尺寸设置,并且你可以在属性面板里自由开启或关闭某个轴向的滚动行为。

../../_images/containers_scroll.png

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

../../_images/containers_center_pan.gif

正如上面的例子中所展示的,使用此容器最常见的方法之一,是将 VBoxContainer 作为子容器一起使用。

AspectRatioContainer

一种容器类型,它会自动排列其子控件,确保在容器大小改变时,子控件的宽高比例能自动保持不变。(通过 AspectRatioContainer 实现)。它拥有多种拉伸模式,提供了多种根据容器大小来调整子控件尺寸的方案,包括:“填充(fill)”、“宽度控制高度(width control height)”、“高度控制宽度(height control width)”以及“覆盖(cover)”

../../_images/containers_aspectratio.webp

当你需要一个能灵活适应不同屏幕尺寸的容器,并且希望里面的子元素能按比例自动缩放、同时还不走样变形时,它就派上大用场啦。

../../_images/containers_aspectratio_drag.webp

FlowContainer

FlowContainer 是一种容器控件,它会把里面的子控件按照水平或者垂直方向进行排列(具体分为 HFlowContainer 水平流式容器 和 VFlowContainer 垂直流式容器)。当一行(或一列)的空间不够用时,它会自动把剩下的子控件“挤”到下一行(或下一列)去,就像书本里的文字自动换行一样。

../../_images/containers_hflow.webp

在创建灵活的布局时它非常有用,里面的子控件会自动根据剩余的空间来调整自身大小,完全不用担心它们会挤在一起或者重叠起来。

../../_images/containers_hflow_drag.webp

CenterContainer

CenterContainer 是一种容器控件,它会自动把里面所有的子控件按照它们的最小尺寸,整齐地居中摆放在自己内部。它能确保子控件始终对齐在正中央,这样你就不用再手动去调位置,轻轻松松就能搞定居中的界面布局啦(具体参考 CenterContainer )。

../../_images/containers_center.webp ../../_images/containers_center_drag.webp

SubViewportContainer

这是一种特殊的控件,它只接受一个 Viewport(视口) 节点作为它的子节点,并且会把这个视口里的画面像显示一张普通图片那样展示出来(具体是通过 SubViewportContainer 来实现的)。

创建自定义容器

可以使用脚本轻松地创建自定义容器。以下是一个能够根据内容自动调整大小的容器示例:

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(), size))

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