布局与参数约定
下拉菜单展开后覆盖其他控件,其他控件仍按 grids 的行列位置排列。滚动内容高度取正常布局高度与菜单实际底边中的较大值。选中、切换或隐藏菜单后重新计算高度;Group 中的菜单会累计各级父组的位移。
下拉菜单的 items 为静态选项列表:每项的 label 是字符串,value 是整数或字符串,两者均不接受 Observable。菜单标题和选中值仍支持 Observable。添加控件时复制选项,修改原始列表不会改变已添加的菜单。
表单根控件的 width、height、offsetX、offsetY 支持通过 Observable 设置为 "default",恢复创建时记录的原生布局。根控件的新尺寸或位移会替换此前尚未完成的过渡。
显示、关闭与追加控件
show() 会检查本次目标玩家。同一玩家已经在显示该表单(包括等待创建的阶段)时,再次调用会抛出 RuntimeError,提示“该表单已经被显示出来了”。检查失败时不会发送新表单或增加关闭监听。关闭后可再次显示;服务端可以分别向尚未显示的玩家调用 show()。
表单显示后仍可调用 button()、label()、group()、custom() 等添加方法。新控件同步到当前显示该表单的玩家,保留已有控件实例,并重新计算布局。表单尚未创建时,新控件加入待创建数据;在 onCreate 内追加的控件在本次创建结束后继续创建,并执行自己的创建回调。
创建期间调用 close() 会取消待显示任务和创建定时器,按 api 原因触发关闭回调。即使旧定时器已进入执行队列,也不会重新创建被关闭的表单或影响重新打开的实例。
创建回调中的实例参数
除 custom 外,所有添加控件方法都在 style 后提供可选的 params 字典,默认为 {}:
form.button(label, callbacks={}, style={}, params={})
form.toggle(label, state, style={}, params={})
form.divider(style={}, params={})
form.label(text, style={}, params={})
form.slider(label, value, minValue=0.0, maxValue=1.0, step=1, style={}, params={})
form.textfield(label, value, style={}, params={})
form.dropdown(label, items, value, style={}, params={})
form.group(children={}, style={}, params={})
form.custom(params={}, style={}) 保持原有顺序。新参数在末尾,不影响已有的位置参数调用;可以用 params=... 省略其他可选参数。
def on_create(args):
print('created button: %s' % args.params.get('name', ''))
# 注册 Button(onCreate=on_create) 后添加多个实例。
form.button('确认', style={'class': 'demo:named_button'}, params={'name': 'confirm'})
form.button('取消', style={'class': 'demo:named_button'}, params={'name': 'cancel'})
onCreate 在客户端通过 args.params 获取当前实例的独立参数快照。参数支持普通可传输值,以及嵌套列表、字典中的 Observable;创建前发生的 Observable 更新会反映在创建快照中。修改快照不会修改源参数、Observable 或表单缓存。参数必须是字典,传入 None、列表或字符串会抛出 TypeError。
Group 根的 params 传给根的创建回调;子控件在 children 的对应名称下单独提供 params,各层不会自动继承或合并参数。普通控件的 params 用于创建回调,不改变原有输入、按钮事件或布局行为,也不会触发 Custom 的 onObservableUpdate。需要 Custom 更新通知时继续使用 form.custom。
创建回调中的实例样式
注册控件的 onCreate(args) 可以通过 args.style 读取当前实例的样式,包括 form.button(..., style=...) 传入的 name 等自定义字段。同一控件类型的不同实例各自获取独立快照;普通按钮、Custom 和 Group 的创建回调均支持。
# -*- coding: utf-8 -*-
from FormUI.lib import Control, Button, Form
def on_create(args):
print('created button: %s' % args.style.get('name', ''))
# 在客户端 FormUI 系统和内置 UI 初始化完成后注册。
Control.register('demo:named_button', 'fui_ore_btns.normal_btn_thin', Button(
onCreate=on_create, buttonPath='/button',
labelPaths=['/default/label', '/hover/label', '/pressed/label'],
))
form = Form.create('按钮示例', {'class': 'oreui:light_panel_thin'})
form.button('确认', style={'class': 'demo:named_button', 'name': 'confirm'})
form.button('取消', style={'class': 'demo:named_button', 'name': 'cancel'})
form.show()
args.style 是调用 onCreate 时合并默认配置后的样式快照,Observable 已递归解包为当前值。尺寸保留 "50%"、"default" 等表达式;Group 的 offset/size 简写会规范化为独立轴属性。它包含实例样式,不包含注册时的 options。
修改快照不会修改表单缓存、Observable 或原生控件。创建后的样式更新不会改变此前保存的快照;运行时调整仍使用绑定的 Observable 或客户端原生控件接口。自定义字段不会自动改变布局或产生事件,需要创建回调自行使用;跨端传输时应使用可传输的数据。
字体大小
form.label(text, {'fontSize': 1.5}) 设置字体缩放倍数,沿用网易原生 SetTextFontSize 的语义,不是像素字号。接受非负有限数值或 Observable;创建时的 "default" 保留模板设置,运行时设置为 "default" 将缩放恢复为 1.0。
font_size = Observable.create(1.0)
form.label('可调整字号', {'fontSize': font_size})
font_size.setValue(1.5)
font_size.setValue('default')
原生接口语义见 网易 SDK 的 SetTextFontSize 文档。
控件注册补发
客户端 UI 初始化完成后会向服务端请求已注册控件,服务端按当前注册表逐项补发。后来加入、重新连接的玩家会收到最新模板路径、完整的注册选项及 Group 定义的当前值。后续注册仍按原有广播流程同步。
滑动条
step=0:连续模式。step<0:按其绝对值计算步长。minValue>maxValue:按数值大小排序边界;原始参数不变。- 两端相等:固定在该值,原生滑动条百分比为零。
- 值和原生百分比超出范围时钳制到有效范围。
- 离散模式以较小边界为起点;较大边界不在步长网格上时,最后一个有效值为不超过它的最大步长值。
- 参数必须是有限数值;不接受布尔值、字符串、NaN 和无穷大。
Observable 修改边界或步长后,滑动条位置、数值标签和轮询缓存一起更新。此时只调整展示值,不主动改写绑定 Observable 中的原始值。
尺寸与位移
支持数值、像素字符串、百分比字符串以及由加减号连接的表达式。字符串可包含小数、负数和科学计数法;没有单位的数字按像素解释。
"50.5%-2.25px"
"72.5%y+2px"
"-.5px"
"12.5"
"100%+-15px"
% 相对父控件当前轴,%x 和 %y 分别相对父控件的宽、高。同一表达式中的百分比须使用同一种参考轴。
"fill" 等价于 "100%";"default" 使用原生默认值。空字符串、错误单位、尾随字符以及不同参考轴的混合百分比会抛出 ValueError。