部件主题(WidgetThemeKey 与 JSON 属性)
基本信息
| 属性 | 值 |
|---|---|
| 注册位置 | api/IThemeApi.java:34-101(接口静态初始化块) |
| 键类 | WidgetThemeKey<T>(theme/WidgetThemeKey.java,161 行) |
| 主题类 | WidgetTheme(102 行)、SlotTheme(50)、TextFieldTheme(59)、SelectableTheme(91) |
| 构建器 | WidgetThemeKeyBuilder(70 行)、WidgetThemeBuilder(65 行) |
| 解析器 | WidgetThemeParser(21 行) |
| id 白名单 | [a-zA-Z0-9$_-]+(theme/ThemeAPI.java:25) |
功能
13 个内置部件主题键
全部在 api/IThemeApi.java 的静态初始化块中注册。
9 个顶层键 + 4 个子键(IThemeApi.java:34-:78):
| # | 键常量 | id | 行 | 类型 | 默认值 |
|---|---|---|---|---|---|
| 1 | FALLBACK |
default |
:34 |
WidgetTheme |
darkTextNoShadow(18, 18, null) |
| 2 | PANEL |
panel |
:38 |
WidgetTheme |
darkTextNoShadow(176, 166, GuiTextures.MC_BACKGROUND) |
| 3 | BUTTON |
button |
:42 |
WidgetTheme |
whiteTextShadow(18, 18, GuiTextures.MC_BUTTON);悬停 MC_BUTTON_HOVERED(:44) |
| 4 | CLOSE_BUTTON |
closeButton |
:48 |
WidgetTheme |
whiteTextShadow(10, 10, GuiTextures.MC_BUTTON);悬停 MC_BUTTON_HOVERED(:50) |
| 5 | SCROLLBAR |
scrollbar |
:53 |
WidgetTheme |
darkTextNoShadow(4, 4, Scrollbar.VANILLA) |
| 6 | ITEM_SLOT |
itemSlot |
:57 |
SlotTheme |
new SlotTheme(GuiTextures.SLOT_ITEM) |
| 7 | FLUID_SLOT |
fluidSlot |
:61 |
SlotTheme |
new SlotTheme(GuiTextures.SLOT_FLUID) |
| 8 | TEXT_FIELD |
textField |
:65 |
TextFieldTheme |
new TextFieldTheme(0xFF2F72A8, 0xFF5F5F5F) |
| 9 | TOGGLE_BUTTON |
toggleButton |
:69 |
SelectableTheme |
whiteTextShadow(18, 18, MC_BUTTON, MC_BUTTON_DISABLED);悬停 (MC_BUTTON_HOVERED, IDrawable.NONE)(:71) |
| 10 | ITEM_SLOT_PLAYER |
itemSlot:player |
:75 |
SlotTheme |
子键,由 #6 createSubKey("player") 生成 |
| 11 | ITEM_SLOT_PLAYER_HOTBAR |
itemSlot:player:playerHotbar |
:76 |
SlotTheme |
子键 |
| 12 | ITEM_SLOT_PLAYER_MAIN_INV |
itemSlot:player:playerMainInventory |
:77 |
SlotTheme |
子键 |
| 13 | ITEM_SLOT_PLAYER_ARMOR |
itemSlot:player:playerArmor |
:78 |
SlotTheme |
子键 |
CLOSE_BUTTON上方有源码注释明确说明它故意不继承button: 「shouldn’t inherit from button -> not a sub theme」(IThemeApi.java:47)。 这一点在类型上体现为:WidgetThemeKey.isSubWidgetTheme()(被DefaultTheme.getWidgetTheme用于向上回溯,theme/DefaultTheme.java:38-41)。
createSubKey 生成的子键用 : 分隔,因此 4 个玩家槽位主题可以整体回退到
itemSlot 的定义,而 itemSlot 再回退到 FALLBACK。
18 个 JSON 属性名
api/IThemeApi.java:83-101 定义了主题 JSON 可识别的属性名常量:
| 组 | 常量 | 行 |
|---|---|---|
| 继承 | PARENT = "parent" |
:83 |
| 尺寸 | DEFAULT_WIDTH = "defaultWidth" |
:84 |
DEFAULT_HEIGHT = "defaultHeight" |
:85 |
|
| 背景 | BACKGROUND = "background" |
:86 |
| 颜色 | COLOR = "color" |
:87 |
TEXT_COLOR = "textColor" |
:88 |
|
TEXT_SHADOW = "textShadow" |
:89 |
|
ICON_COLOR = "iconColor" |
:90 |
|
| 槽位专用 | SLOT_HOVER_COLOR = "slotHoverColor" |
:91 |
SLOT_CUSTOM_TEXTURES = "useCustomSlotTextures" |
:92 |
|
SLOT_INVENTORY_BACKGROUND = "inventorySlotBackground" |
:93 |
|
SLOT_HOTBAR_BACKGROUND = "hotbarSlotBackground" |
:94 |
|
| 提示 | MARKED_COLOR = "markedColor" |
:95 |
HINT_COLOR = "hintColor" |
:96 |
|
| 选中态 | SELECTED_BACKGROUND = "selectedBackground" |
:97 |
SELECTED_COLOR = "selectedColor" |
:98 |
|
SELECTED_TEXT_COLOR = "selectedTextColor" |
:99 |
|
SELECTED_TEXT_SHADOW = "selectedTextShadow" |
:100 |
|
SELECTED_ICON_COLOR = "selectedIconColor" |
:101 |
外加 1 个悬停后缀常量 HOVER_SUFFIX = ":hover"(:80),
即悬停主题写作 <id>:hover。
注册自定义部件主题
IThemeApi api = IThemeApi.get();
WidgetThemeKey<MyTheme> KEY = api.registerWidgetTheme(
"myWidget", new MyTheme(...), new MyTheme(...), MyTheme::new);
(IThemeApi.java:231 的签名 + :222-230 的 javadoc 建议「把 key 存成 static 变量」。)
等价的链式写法是 widgetThemeKeyBuilder(id, type).defaultTheme(...).register()
(IThemeApi.java:233-235),内置的 13 个键都是这样写的。
约束(theme/ThemeAPI.java:100-115):
| 约束 | 违反后果 | 行 |
|---|---|---|
id 非 null |
NullPointerException(:104) |
:104 |
defaultTheme 非 null |
NullPointerException(:105) |
:105 |
parser 非 null |
NullPointerException(:106) |
:106 |
id 不重复 |
IllegalStateException |
:107-109 |
id 匹配 [a-zA-Z0-9$_-]+ |
IllegalArgumentException |
:110-112 |
数值
| 数值名 | 值 | 来源 |
|---|---|---|
| 部件主题键总数 | 13(9 顶层 + 4 子键) | api/IThemeApi.java:34-78 |
| JSON 属性名总数 | 18 | api/IThemeApi.java:83-101 |
| 面板默认尺寸 | 176 × 166 | api/IThemeApi.java:39 |
| 按钮默认尺寸 | 18 × 18 | api/IThemeApi.java:43 |
| 关闭按钮默认尺寸 | 10 × 10 | api/IThemeApi.java:49 |
| 滚动条默认尺寸 | 4 × 4 | api/IThemeApi.java:54 |
| 兜底默认尺寸 | 18 × 18 | api/IThemeApi.java:35 |
| 文本框主色 / 次色 | 0xFF2F72A8 / 0xFF5F5F5F |
api/IThemeApi.java:66 |
交互
| 触发 | 行为 |
|---|---|
| 控件绘制 | Widget.getWidgetTheme(ITheme)(widget/Widget.java:365)取当前主题的部件定义 |
| 指定主题 | getWidgetTheme(ITheme, Class<T>)(:386)带类型检查 |
| 控件级覆盖 | Widget.widgetTheme(String)(:537)/ widgetTheme(WidgetThemeKey<?>)(:551);读取用 getWidgetThemeOverride()(:372) |
| 悬停 | 自动查 <id>:hover |
| 主题缺失 | 沿 isSubWidgetTheme() 链向上回溯(theme/DefaultTheme.java:38-41),最终落到 FALLBACK |