Summary: 本文介绍了UE4中的自由布局选项,Canvas和Overlay。Canvas用于指定子控件的位置和尺寸,而Overlay按顺序堆叠子控件,共享相同的坐标。文章解释了如何在Canvas中使用位置、对齐、尺寸、内容填充和颜色,以及如何在各种情况下应用Overlay。
Canvas¶
SCanvas正如它的名字,和画布一样,可以指定子控件的位置和尺寸。一些复杂的,需要固定位置和尺寸的控件用Canvas布局就会很方便。比如下面例子中的“Rigging Tool”中,“角色”的各个部分是是通过Canvas lay
"Root":{
"SBorder": {
"BorderImage": {
"Style": "FEditorStyle",
"Brush": "ToolPanel.DarkGroupBorder"
},
"Content":{
"Padding": [0, 20],
"SCanvas": {
"ToolTipText": "Canvas is a layout widget that allows you to arbitrary position and size child widgets in a relative coordinate space",
"Slots": [
{
"Position": [97.5, 0],
"Size": [25, 20],
"SButton": {"ButtonColorAndOpacity": [0, 5, 0 ,1], "OnClick": "print('Head.')",
"ContentPadding": [-8, 0],
"Text": "^_^",
"ToolTipText": "Head"
}
},
{
"Position": [90, 22],
"Size": [40, 40],
"SButton": {"ButtonColorAndOpacity": [0, 2, 0 ,1], "OnClick": "print('Body.')"}
},
{
"Position": [70, 25],
"Size": [15, 40],
"SButton": {"ButtonColorAndOpacity": [2, 0, 0 ,1], "OnClick": "print('Right Arm.')"}
},
{
"Position": [135, 25],
"Size": [15, 40],
"SButton": {"ButtonColorAndOpacity": [0, 0, 2 ,1], "OnClick": "print('Left Arm.')"}
},
{
"Position": [95, 65],
"Size": [15, 25],
"SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Upper Leg.')"}
},
{
"Position": [112, 65],
"Size": [15, 25],
"SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Upper Leg.')"}
},
{
"Position": [95, 92],
"Size": [15, 27],
"SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Leg.')"}
},
{
"Position": [112, 92],
"Size": [15, 27],
"SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Leg.')"}
}
]
}
}
}
}
Position¶
!!! 注意,这里的"Position"是相对位置,因此,如果我们想要整体调整按钮的位置,可以通过控制SCanvas自身或者其父组件的位置来做。
例如,下面的"Padding": [0, 20]
讲SCanvas向下一定了20px。当然,更严谨的写法是 "Padding": [0, 0, 0, 20]
,这样不会影响Canvas下方的组件。
"Padding": [0, 20],
"SCanvas": {
...
}
HAlign/VAlign¶
SCanvas组件中的子控件,默认是以"HAlign": "Left"
, "VAlign": "Top"
对齐到目标坐标的。
之前的腿部部分的代码,将ui左侧的角色的右脚按钮设置为向右对齐,Position也为"Position": [112, 65],
。
{
"Position": [95, 65],
"Size": [15, 25],
"SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Upper Leg.')"}
},
{
"Position": [112, 65],
"Size": [15, 25],
"SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Upper Leg.')"}
},
改为:
{
"Position": [112, 65],
"Size": [15, 25],
"HAlign": "Right",
"SButton": {"ButtonColorAndOpacity": [1, 0, 0 ,1], "OnClick": "print('Right Upper Leg.')"}
},
{
"Position": [112, 65],
"Size": [15, 25],
"SButton": {"ButtonColorAndOpacity": [0, 0, 1 ,1], "OnClick": "print('Left Upper Leg.')"}
},
左右脚按钮会分别对齐的中线:[112, 65]
的位置
"VAlign" 也时同理,可以控制控件与目标坐标的对齐方式。
"HAlign"可选值:
- "Left"
- "Center"
- "Right"
VAlign可选值:
- "Top"
- "Center"
- "Bottom"
Size¶
Size
属性将设置子控件的尺寸
注意,Canvas 的Slot 没有"Padding"属性,因此不能在指定位置之后再次通过"Padding"来进行微调
按钮的 Content Padding 和 Color¶
Content Padding¶
有读者可能会注意到,上面头部按钮的代码中,我们使用了"ContentPadding": [-8, 0]
,这个奇怪的属性。
如果我们删除它,将会发现按钮中的文章 "Text": "^_^"
将显示不出来。这是因为UE5在计算按钮尺寸时,左右各额外加上了8px,使得按钮尺寸过小时,上面的文本内容被空白区域遮挡。具体的详细说明可见这里ContentPadding
Color¶
同样还是头部的按钮,这里我们使用了"SButton": {"ButtonColorAndOpacity": [0, 5, 0, 1]
, 用一个数值为unreal.LinearColor(0,5,0,1)
的线性颜色为按钮的背景设置颜色。
注意,这里颜色值大于1了,目的是将其与按钮的暗色背景相乘,使得最终获得一个亮绿色。Hacky:D
Overlay¶
SOverlay布局会将各个子控件依次重叠排列,代码中靠后的Slot会依次覆盖在之前的Slot之上。各个Slot共享同样的坐标。
所以,如果我们将上面例子中的SCanvas放入到SOverlay布局中,并在并列的地方加上一个按钮,就会获得这样一个诡异的结果:
"SOverlay":
{
"Slots": [
{
"SCanvas": {
"ToolTipText": "Canvas is a layout widget that allows you to arbitrary position and size child widgets in a relative coordinate space",
"Slots": [...]
}
},
{
"SButton": { "Text": "A Big Opacity Button", "ButtonColorAndOpacity": [1, 0, 0, 0.3],
"VAlign": "Center",
"HAlign": "Center"
}
}
]
}
一个半透明的按钮覆盖在了之前的"Rigging" 按钮上,并且处理了所有的点击事件,(下方的按钮无法被点击)
应用¶
更创建的按钮是将图片作为工具的背景图,比如在地图编辑器的各个Tile的按钮下方,放上背景图片
或者将多个控件进行组合使用,比如将SButton 和SEditableText放在一起,使得控件能够有可编辑的文本和按钮
"SOverlay": {
"Slots": [{
"SButton": {"ButtonStyle": {"Style": "FEditorStyle", "StyleName": "HoverHintOnly"}, "ContentPadding": [16, 0],
"OnClick": "chameleon_shelf.on_button_click(id=0)",
"Content": { "SImage": {"Aka": "Img_0", "ImagePathInPlugin": "Resources/PythonGreyIcon_40x.png", "ColorAndOpacity": [1,1,1,0.6]}}
}
},{
"Padding": [0, 20, 0, 0],
"SEditableText":{"Aka": "Txt_0", "Text": "", "ColorAndOpacity": [1,1,1,1], "Justification": "Right"}
}
]
}
关于Shelf Tools 的具体解释可以看这里:Shelf Tools