快速入门
使用 Java 和 KubeJS 创建 UI 的方式基本相同。本页将介绍创建和使用 UI 的基本流程。
整个 UI 创建与使用流程 包含以下步骤:
-
创建
UI组件与布局 (1)- 创建
Button和Item Slot,设置它们的位置……
- 创建
-
绑定
UI功能逻辑 (1)- 添加
Button被点击时执行的逻辑,将Inventory绑定到Item Slot……
- 添加
-
显示
UI(1)- 右键物品时打开
GUI,右击方块时打开GUI……
- 右键物品时打开
从技术上讲,UI 功能绑定和 UI 组件创建的过程是同时进行的,因为许多控件都提供了在创建时就绑定功能的构造函数。
在本页中,为了更清晰地展示 UI 的工作原理,我们在代码示例中将步骤 1 和步骤 2分开讲解。
创建 UI 组件与布局
让我们从 WidgetGroup 开始,它是一个用于容纳子组件的容器。因此,我们创建一个 WidgetGroup 作为根组件。在此处查看所有组件。
然后,我们向其中添加一个 Label 和一个 Button。
public WidgetGroup createUI() {
// 创建根容器
var root = new WidgetGroup();
root.setSize(100, 100);
root.setBackground(ResourceBorderTexture.BORDERED_BACKGROUND);
// 创建 Label 和 Button
var label = new LabelWidget();
label.setSelfPosition(20, 20);
label.setText("Hello, World!");
var button = new ButtonWidget();
button.setSelfPosition(20, 60);
button.setSize(60, 20);
// 准备 Button 纹理
var backgroundImage = ResourceBorderTexture.BUTTON_COMMON;
var hoverImage = backgroundImage.copy().setColor(ColorPattern.CYAN.color);
var textAbove = new TextTexture("Click me!");
button.setButtonTexture(backgroundImage, textAbove);
button.setClickedTexture(hoverImage, textAbove);
// 将 Label 和 Button 添加到根容器
root.addWidgets(label, button);
return root;
}
function createUI() {
// 创建根容器
let root = new WidgetGroup();
root.setSize(100, 100);
root.setBackground(ResourceBorderTexture.BORDERED_BACKGROUND);
// 创建 Label 和 Button
let label = new LabelWidget();
label.setSelfPosition(20, 20);
label.setText("Hello, World!");
let button = new ButtonWidget();
button.setSelfPosition(20, 60);
button.setSize(60, 20);
// 准备 Button 纹理
let backgroundImage = ResourceBorderTexture.BUTTON_COMMON;
let hoverImage = backgroundImage.copy().setColor(ColorPattern.CYAN.color);
let textAbove = new TextTexture("Click me!");
button.setButtonTexture(backgroundImage, textAbove);
button.setClickedTexture(hoverImage, textAbove);
// 将 Label 和 Button 添加到根容器
root.addWidgets(label, button);
return root;
}
绑定 UI 功能逻辑
创建 UI 后,我们需要实现其逻辑。例如,我们希望点击 Button 来更改 Label 的文本。
显示 UI
现在,让我们显示我们创建的 UI!我们需要指定一个 UI Factory 来显示 UI,它负责管理 UI 的生命周期。
共有四个步骤:
open uicreate UI in server sidenotify to open UIcreate UI in remote side
sequenceDiagram
autonumber
Note left of Server: 1. open UI
Note left of Server: 2. create UI in server side
Server->>Remote: 3. notify to open UI
Note right of Remote: 4. create UI in remote side
UI Factory 将协助处理 step 3。因此,用户需要定义何时触发 step 1,以及在 step 2 和 step 4 中创建什么。通常情况下,服务端和远程端创建的 UI 在大多数情况中都是相同的。
LDLib 提供了两种内置工厂:
Block Entity UI FactoryHeld Item UI Factory
Block Entity UI Factory
此工厂允许用户从方块打开 UI。
Java
-
Java 用户应为自己的
BlockEntity实现IUIHolder.Block,并实现createUI(Player entityPlayer)方法。 -
在想要打开
UI时,调用BlockEntityUIFactory.INSTANCE.openUI()方法。
KubeJS
KubeJS 用户可以用更简单的方式实现同样的功能。用户甚至可以为方块(无实体)打开 UI,但相比 Java 可访问性较低。
- KubeJS 用户应使用
LDLibUI.block(ui_name, e => {})根据给定的ui_name创建UI。 - 在想要打开
UI时,调用BlockUIFactory.INSTANCE.openUI(player, pos, ui_name)方法。
public class TestBlockEntity extends BlockEntity implements IUIHolder {
public void onPlayerUse(Player player) {
// 在此处执行 step 1
if (player instanceof ServerPlayer serverPlayer) {
BlockEntityUIFactory.INSTANCE.openUI(this, serverPlayer);
}
}
private WidgetGroup createUI() {
// ....
}
@Override
public ModularUI createUI(Player entityPlayer) {
// 在此处执行 step 2 和 step 4
return new ModularUI(createUI(), this, entityPlayer);
}
}
// 服务端脚本
BlockEvents.rightClicked('test_block_ui', event => {
// 在此处执行 step 1
BlockUIFactory.INSTANCE.openUI(event.player, event.block.pos, "test_block_ui");
})
function createUI() {
// ....
}
LDLibUI.block("test_block_ui", e => {
// 在此处执行 step 2 和 step 4
// let level = e.level
// let pos = e.pos
// let block = e.block
// let player = e.player
var ui = createUI();
e.success(ui);
})
Held Item UI Factory
此工厂允许用户从手持物品打开 UI。
Java
-
Java 用户应为自己的
Item实现IUIHolder.Item,并实现createUI(Player entityPlayer, HeldItemUIFactory.HeldItemHolder holder)方法。 -
在想要打开
UI时,调用HeldItemUIFactory.INSTANCE.openUI()方法。
KubeJS
KubeJS 用户可以用更简单的方式实现同样的功能。用户甚至可以为方块(无实体)打开 UI,但相比 Java 可访问性较低。
- KubeJS 用户应使用
LDLibUI.item(ui_name, e => {})根据给定的ui_name创建UI。 - 在想要打开
UI时,调用ItemUIFactory.INSTANCE.openUI(player, hand, ui_name)方法。
public class TestItem implements IUIHolder.Item {
@Override
public InteractionResult useOn(UseOnContext context) {
// 在此处执行 step 1
if (context.getPlayer() instanceof ServerPlayer serverPlayer) {
HeldItemUIFactory.INSTANCE.openUI(serverPlayer, context.getHand());
}
return InteractionResult.SUCCESS;
}
private WidgetGroup createUI() {
// ....
}
@Override
public ModularUI createUI(Player entityPlayer, HeldItemUIFactory.HeldItemHolder holder) {
// step 2 和 step 4
return new ModularUI(createUI(), holder, entityPlayer);
}
}
// 服务端脚本
ItemEvents.firstRightClicked('minecraft:stick', event => {
// 在此处执行 step 1
ItemUIFactory.INSTANCE.openUI(event.player, event.hand, "test_item_ui");
})
function createUI() {
// ....
}
LDLibUI.item("test_item_ui", e => {
// step 2 和 step 4
// let player = e.player
// let hand = e.hand
// let held = e.held
var ui = createUI();
e.success(ui);
})