Handles: enable, hide, tooltip
Every add… method returns a handle. It keeps the element's state before and after the window opens, so you can disable a button, hide a line or explain a choice with a tooltip.
The three states
An ElementHandle changes three things on any element:
| State | Method | Effect |
|---|---|---|
| Disabled | setEnabled(false) | Drawn in a muted colour, ignores mouse and keyboard. The tooltip still shows on hover, to explain why. |
| Hidden | setVisible(false) | Not drawn and frees its space: the window lays itself out again without it. |
| Tooltip | setTooltip(text) | Text shown when the element is hovered. null removes it. |
ElementHandle confirm = window.addButton(Component.literal("Confirm"), this::confirm);confirm.setEnabled(false);confirm.setTooltip(Component.literal("Fill in the form first"));ElementHandle details = window.addText(Component.literal("Details..."));details.setVisible(false); // the element disappears and frees its spaceA change made while the window is shown is visible on the next frame. Call handles on the client thread.
Why the state lives in the handle
Minecraft rebuilds widgets on every resize. The state lives in the handle, not in the shown widget, so a checked box stays checked and a hidden line stays hidden: the new widgets read the state back.
Connect elements together
Handles make it easy to tie elements to each other. Enable "Take" only when a line is selected:
ElementHandle take = buttons.addButton(Component.literal("Take"), this::take);take.setEnabled(false);list.onSelect(index -> take.setEnabled(index >= 0));Show a line only while a checkbox is ticked:
ElementHandle detail = window.addText(Component.literal("12 items, 3 different kinds"));detail.setVisible(false);CheckboxHandle showDetail = window.addCheckbox(Component.literal("Show details"), false);showDetail.onChange(detail::setVisible);Specialised handles
Some elements return a handle with more methods. All of them are also an ElementHandle.
| Handle | Returned by | Adds |
|---|---|---|
CheckboxHandle | addCheckbox | isChecked, setChecked, onChange |
ListHandle | addList | setLines, addLine, getSelected, onSelect |
SearchHandle | addSearch | getText, setText, onChange (every keystroke) |
ProgressHandle | addProgress | setProgress(0..1), setProgress(done, total), setLabel |
RowHandle | addRow | addText, addButton, addIconButton, addCheckbox |
TabsHandle | addTabs | addTab, getSelected, setSelected, onSelect |
onChange and onSelect keep only one action: a new call replaces the previous one. They fire when the value really changes, whether the change comes from the player or from your code.
Rows and tabs
On a row or a tab row, the three states apply to everything inside:
- disabled, a row disables all its elements; a tab row can no longer be switched, and the shown content is disabled too;
- hidden, it disappears with its content and frees its space;
- tooltip: on a row, it shows on the elements that have none of their own; on a tab row, only when the tabs are hovered, not the content.
Progress bars
A ProgressHandle is read every frame: update it as often as you like, every tick for instance, without rebuilding the screen.
ProgressHandle craft = window.addProgress(Component.literal("Iron ingots: 0 / 64"));craft.setProgress(16, 64);craft.setLabel(Component.literal("Iron ingots: 16 / 64"));The bar width is computed when the screen is built, from the text. A longer text given later is cut with "…" until the next rebuild.