自定义UI对话框
通过在脚本头部添加 UI 配置,可以创建图形化参数输入对话框,让用户更方便地使用脚本。
UI 配置格式
支持两种格式:
格式 1:单行注释格式
# UI: {"fields":[字段1, 字段2, ...]}
适合字段较少、配置简单的情况。
示例:
# UI: {"fields":[{"name":"count","field_type":"number","label":"数量:","default_value":"10","options":[]}]}
格式 2:三引号字符串格式(推荐)
单行:
"""UI:{"fields":[字段1, 字段2, ...]}"""
多行(推荐用于复杂配置):
"""UI:{
"fields": [
{
"name": "start_time",
"field_type": "number",
"label": "起始时间 (ms):",
"default_value": "0",
"options": []
},
{
"name": "operation",
"field_type": "select",
"label": "操作类型:",
"default_value": "cut",
"options": ["cut", "copy", "delete"]
}
]
}"""
字段配置
每个字段是一个 JSON 对象,包含以下属性:
{
"name": "参数名称",
"field_type": "字段类型",
"label": "显示标签",
"default_value": "默认值",
"options": ["选项1", "选项2"]
}
属性说明
| 属性 | 说明 | 必需 |
|---|---|---|
name | 参数变量名,用于在代码中获取值 | 是 |
field_type | 字段类型(见下表) | 是 |
label | 在UI中显示的标签文本 | 是 |
default_value | 默认值(字符串格式) | 是 |
options | 下拉框的选项列表(仅 select 类型需要) | 否 |
支持的字段类型
| 类型 | UI 控件 | 说明 | 示例默认值 |
|---|---|---|---|
text | 文本输入框 | 单行文本输入 | "Hello" |
number | 数字输入框 | 数字输入,带提示 | "100" |
bool | 复选框 | 布尔值选择 | "true" 或 "false" |
select | 下拉选择框 | 从预定义选项中选择 | "option1" |
注意:
select类型必须提供options数组- 所有
default_value都是字符串格式 bool类型的值为"true"或"false"(字符串)
参数获取方式
使用自定义UI时,参数以 JSON 字符串形式传递:
import sys
import json
def main():
if len(sys.argv) < 2:
print("错误:未提供参数")
return
try:
# 解析从自定义UI传来的JSON参数
params = json.loads(sys.argv[1])
# 获取参数值
start_time = float(params.get('start_time', '0'))
end_time = float(params.get('end_time', '10000'))
keep_notes = params.get('keep_notes', 'true') == 'true'
operation = params.get('operation', 'cut')
print(f"起始时间: {start_time}")
print(f"结束时间: {end_time}")
print(f"保留Note: {keep_notes}")
print(f"操作类型: {operation}")
except json.JSONDecodeError as e:
print(f"错误:无法解析参数 - {e}")
关键点:
- 所有参数打包成一个 JSON 字符串
- 通过
sys.argv[1]获取 - 使用
json.loads()解析 - 参数值都是字符串,需要手动转换类型
完整示例
示例 1:多种字段类型
# Description: 处理谱面的轨道Note
"""UI:{
"fields": [
{
"name": "start_time",
"field_type": "number",
"label": "起始时间 (ms):",
"default_value": "0",
"options": []
},
{
"name": "end_time",
"field_type": "number",
"label": "结束时间 (ms):",
"default_value": "10000",
"options": []
},
{
"name": "keep_notes",
"field_type": "bool",
"label": "保留该范围内的Note?",
"default_value": "true",
"options": []
},
{
"name": "operation",
"field_type": "select",
"label": "操作类型:",
"default_value": "cut",
"options": ["cut", "copy", "delete", "move"]
}
]
}"""
import sys
import json
from rct_api import get_current_chart, save_current_chart
def main():
if len(sys.argv) < 2:
print("错误:未提供参数")
return
try:
params = json.loads(sys.argv[1])
start_time = float(params.get('start_time', '0'))
end_time = float(params.get('end_time', '10000'))
keep_notes = params.get('keep_notes', 'true') == 'true'
operation = params.get('operation', 'cut')
chart = get_current_chart()
if not chart:
print("错误:无法获取谱面")
return
# 处理逻辑
print(f"执行 {operation} 操作: {start_time}ms - {end_time}ms")
if keep_notes:
chart.filter_notes_by_time(start_time, end_time)
else:
# 反向过滤逻辑...
pass
save_current_chart(chart)
print("处理完成")
except json.JSONDecodeError as e:
print(f"错误:无法解析参数 - {e}")
except Exception as e:
print(f"错误:{e}")
if __name__ == "__main__":
main()
示例 2:简单的单字段
# Description: 生成指定数量的Note
# UI: {"fields":[{"name":"count","field_type":"number","label":"Note数量:","default_value":"10","options":[]}]}
import sys
import json
from rct_api import get_current_chart, save_current_chart, Note
def main():
if len(sys.argv) < 2:
return
params = json.loads(sys.argv[1])
count = int(params.get('count', '10'))
chart = get_current_chart()
if not chart:
return
for i in range(count):
time = i * 1000
degree = (i * 45) % 360
chart.add_note(Note.TAP, time, degree)
chart.sort()
save_current_chart(chart)
print(f"生成了 {count} 个Note")
if __name__ == "__main__":
main()
示例 3:文本输入
# Description: 搜索并标记特定角度的Note
"""UI:{
"fields": [
{
"name": "degree",
"field_type": "number",
"label": "目标角度:",
"default_value": "0",
"options": []
},
{
"name": "tolerance",
"field_type": "number",
"label": "误差范围:",
"default_value": "5",
"options": []
},
{
"name": "comment",
"field_type": "text",
"label": "备注信息:",
"default_value": "已标记",
"options": []
}
]
}"""
import sys
import json
from rct_api import get_current_chart
def main():
if len(sys.argv) < 2:
return
params = json.loads(sys.argv[1])
target_degree = float(params.get('degree', '0'))
tolerance = float(params.get('tolerance', '5'))
comment = params.get('comment', '已标记')
chart = get_current_chart()
if not chart:
return
found_count = 0
for note in chart.notes:
if abs(note.degree - target_degree) <= tolerance:
found_count += 1
print(f"找到Note: 时间={note.time}ms, 角度={note.degree}° - {comment}")
print(f"共找到 {found_count} 个符合条件的Note")
if __name__ == "__main__":
main()